7

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

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

给出:

-2147483648
0

这个行为标准是定义的还是实现定义的?还有其他情况会导致除法运算溢出吗?是否存在模运算符会溢出的情况?

4

3 回答 3

11

根据CERT C++ 安全编码标准,模数可以溢出它说:

[...]当被除数等于有符号整数类型的最小(负)值并且除数等于 -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++ 标准草案标准部分5.6 乘法运算符4段说(强调我的):

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

CERT 文档的C 版本提供了一些关于如何在某些平台上工作的更多见解,%并且在某些情况下INT_MIN % -1可能会产生浮点异常

/ 的防止溢出的逻辑与上面的 . 的逻辑相同%

于 2013-10-10T01:20:16.407 回答
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
于 2013-10-10T00:47:17.373 回答
0

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

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

于 2013-10-10T00:44:05.013 回答