C++整数除法如何计算极限值和负值?

How does C++ integer division work for limit and negative values?

我在 C++ 中遇到整数除法的一些奇怪结果。我正在尝试计算:-2147483648 / -1.

我得到的是 3 种不同情况下的 3 种不同结果:

int foo(int numerator, int denominator) {
    int res = numerator / denominator; // produces SIGFPE, Arithmetic exception interrupt

    cout << res << endl;
}

int main() {
    int res = -2147483648 / -1;
    cout << res << endl;               // prints -2147483648
    cout << -2147483648 / -1 << endl;  // prints 2147483648
    foo(-2147483648, -1);
    return 0;
}

为什么整数除法运算在不同情况下会产生不同的结果?

你的结果可能是INT_MAX+1,换句话说它可能溢出了。那是未定义的行为,任何事情都可能发生。例如,编译器可能会完全拒绝代码。

(一个系统可能有 INT_MAX >= 2147483648,但你会期望你的 3 个测试用例得到相同的结果)

编译器将文字 -2147483648 / -1 计算为 2147483648,数据类型的宽度足以容纳该值。

当直接打印文字时,它会正确打印值。

当文字存储在 res 中时,它被转换为 intint 在您的系统上似乎是 32 位宽。值 2147483648 不能表示为 32 位有符号整数,因此转换会导致溢出。在您的系统上,此溢出导致值 -2147483648(可能使用二进制补码)。

最后,当试图在运行时执行除法时(在foo函数中),由于溢出而发生SIGFPE异常(因为int数据类型不能表示结果)。

请注意,所有这三个选项都依赖于平台相关行为:

  • 事实是当文字计算溢出时编译器不会生成任何错误(或其他问题)并且只使用足够大的数据类型来保存结果
  • 事实是 int 在存储文字时溢出会生成该特定值(没有其他问题)
  • 运行时溢出时抛出SIGFPE异常的事实
int res = -2147483648 / -1;
cout << res << endl;               // prints -2147483648
cout << -2147483648 / -1 << endl;  // prints 2147483648
int res = numerator / denominator; // produces SIGFPE, Arithmetic exception interrupt

请注意,没有负数 integer literals

There are no negative integer literals. Expressions such as -1 apply the unary minus operator to the value represented by the literal, which may involve implicit type conversions.

字面值 2147483648 大于 int 的最大值,因此其类型将是 long(或 long long,取决于实现)。那么-2147483648的类型是long,计算结果(-2147483648 / -1)也是long

对于第一种情况,long类型的结果2147483648implicitly convertedint,但它大于int的最大值,结果是实现定义的。 (这里好像是按照表示规则(2的补码)进行了回绕,所以得到结果-2147483648。)

对于第二种情况,类型为long的结果是直接打印出来的,所以得到正确的结果。

对于第三种情况,您正在对两个 int 进行计算,结果不符合结果类型(即 int),signed integer arithmetic operation overflow发生了,行为未定义。 (在这里产生 SIGFPE,算术异常中断。)