Integer Overflow

今天做了一个实验,就是对一些数据的边界进行测试,结果竟然抛异常终止了。


这有点出乎我的意料,因为并不是除0错,我以为会忽略溢出呢。后来看了资料,才明白是怎么回事。


首先,32bit整数的表达范围是 -2147483648 ~ 2147483647,我们可以看到INT_MIN的定义是( - 2147483647 - 1 ),据《深入理解计算机系统》里面讲述,这是因为将一个字符串解析成数字,如果是这样:


int parse_int( char* str ) {
    int  sign = 0, ans = 0;
    if( *str == '-' ) { ++str; sign = 1; }
    while( '0' <= *str && *str <= '9' ) {
        ans = ans * 10 + *str++ - '0';
    }
    return  sign ? -ans : ans;
}

那么就会导致ans在计算2147483648的时候溢出(因为ans无法保存2147483648),那么再取反也是不对的。我不知道当前主流编译器是不是用这么弱的方法解析(因为既然scanf和cin都没有问题,显然编译器也可以采用同样的方法),可能这么写是为了兼容古老的编译器吧。


但是我们也知道,有一些加减法或乘法溢出,是不会报错的,甚至我们还利用了这个特点做一些运算。但是今天我遇到了一个除法出错的情况。

int  x, y;
std::cin >> x >> y;
std::cout << (x / y) << std::endl;

如果输入x = -2147483648  y = -1就会出错,在VS2012中弹出“unhandled exception xxx Integer Overflow”,在GCC中更可恶,提示“浮点数异常”,如果我的测试代码包含了浮点数运算,那我肯定只检查浮点数那里了,这个一定要注意!!!


实际上,C语言中,对于有符号整型运算的溢出是未定义的行为,而无符号整数则将溢出的部分舍去,取结果的低位部分作为结果。(In the C programming language, signed integer overflow causes undefined behavior, while unsigned integer overflow causes the number to be reduced modulo a power of two, meaning that unsigned integers "wrap around" on overflow.


另外就是Linux中的信号有一个是SIGFPE,当执行算术运算出错时抛出,例如除0错。看字面意思是Floating-Point Error才对,可是整型确实也用到了它。

SIGFPE
The SIGFPE signal is sent to a process when it executes an erroneous arithmetic operation, such as division by zero.


参考资料:

http://en.wikipedia.org/wiki/Integer_overflow

http://en.wikipedia.org/wiki/SIGFPE#SIGFPE




你可能感兴趣的:(Integer Overflow)