提问者:小点点

C整数除法如何处理极限值和负值?


我在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;
}

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


共3个答案

匿名用户

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

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

当文本存储在res中时,它将转换为int。在您的系统上,int的宽度为32位。值2147483648不能表示为32位有符号整数,因此强制转换会导致溢出。在您的系统上,此溢出导致值为2147483648(可能是使用了2的补码)。

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

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

  • 事实上,当文字计算溢出时,编译器不会生成任何错误(或其他问题),只使用足够大的数据类型来保存结果
  • 存储文本时,int溢出会生成特定的值(没有其他问题)
  • 在运行时溢出时引发SIGFPE异常的事实

匿名用户

您的结果可能是INT\u MAX 1,换句话说,它可能溢出。这是未定义的行为,任何事情都可能发生。例如,编译器可能会完全拒绝代码。

(系统可能具有INT\u MAX

匿名用户

int res = -2147483648 / -1;
cout << res << endl;               // prints -2147483648
cout << -2147483648 / -1 << endl;  // prints 2147483648
int res = numerator / denominator; // produces SIGFPE, Arithmetic exception interrupt

请注意,没有负整数文本。

没有负整数文字。-1等表达式将一元减运算符应用于文字表示的值,这可能涉及隐式类型转换。

文字值2147483648大于int的最大值,因此其类型将为long(或long-long,具体取决于实现)。然后,-2147483648的类型是长的,计算结果(-2147483648/-1)也是长的。

对于第一种情况,类型为长的结果被隐式转换为int,但它大于int的最大值,结果是实现定义的。(结果似乎是根据此处表示(2的补码)的规则进行包装的,因此您得到的结果是2147483648)

对于第二种情况,带有long类型的结果直接打印出来,因此您得到正确的结果。

对于第三种情况,您正在对两个int进行计算,结果不能符合结果类型(即int),发生了有符号整数算术运算溢出,行为未定义。(此处产生SIGFPE,算术异常中断。)

相关问题