模数是否溢出?

时间:2013-10-10 00:38:38

标签: c++ visual-c++ c++11 integer-overflow

我知道(INT_MIN / -1)溢出,但(INT_MIN%-1)没有溢出。至少这是两个编译器中发生的事情,一个是前c ++ 11(VC ++ 2010),另一个是后c ++ 11 GCC 4.8.1

int x = INT_MIN;
cout << x / -1 << endl; 
cout << x % -1 << endl;

给出:

-2147483648
0

此行为标准是定义的还是实现定义的? 还有其他任何情况下除法操作会溢出吗? 并且模数运算符是否会溢出?

3 个答案:

答案 0 :(得分:11)

根据CERT C++ Secure Coding Standard模数可以can overflow它说:

  

[...]当被除数等于有符号整数类型的最小(负)值并且除数等于-1时,在模运算期间可能发生溢出。

他们建议采用以下检查方式以防止溢出:

signed long sl1, sl2, result;

/* Initialize sl1 and sl2 */

if ( (sl2 == 0 ) || ( (sl1 == LONG_MIN) && (sl2 == -1) ) ) {
  /* handle error condition */
}
else {
  result = sl1 % sl2;
}

C++ draft standard部分5.6 乘法运算符 4 表示(强调我的):

  

二元/运算符产生商,二元%运算符从第一个表达式除以第二个表达式得到余数。如果/或%的第二个操作数为零,则行为未定义。对于积分操作数,/运算符产生代数商,丢弃任何小数部分; 81 如果商a / b在结果类型中可表示,(a / b)* b + a%b等于a;否则,a / b和%b的行为都是未定义的。

C version of the CERT document提供了一些关于%如何在某些平台上运行的更多信息,在某些情况下,INT_MIN % -1可能会产生浮点异常

preventing overflow for /的逻辑与%的上述逻辑相同。

答案 1 :(得分:1)

导致溢出的模运算不是:

int x = INT_MIN;
int a = x / -1; // int's are 2's complement, so this is effectively -INT_MIN which overflows
int b = x % -1; // there is never a non-0 result for a anything +/- 1 as there is no remainder

答案 2 :(得分:0)

C ++语言的每个现代实现都使用二进制补码作为整数的底层表示方案。因此,-INT_MIN永远不能表示为int。 (INT_MAX是-1 + INT_MIN)。存在溢出,因为当x是INT_MIN时,值x / -1不能表示为int。

想想%计算什么。如果结果可以表示为int,则不会有任何溢出。