我在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;
}
为什么整数除法运算在不同的情况下产生不同的结果?
编译器将文本2147483648/-1计算为2147483648,数据类型的宽度足以容纳该值。
直接打印文本时,它会正确打印值。
当文本存储在res中时,它将转换为int。在您的系统上,int的宽度为32位。值2147483648不能表示为32位有符号整数,因此强制转换会导致溢出。在您的系统上,此溢出导致值为2147483648(可能是使用了2的补码)。
最后,当尝试在运行时执行除法时(在foo
函数中),由于溢出而发生SIGFPE
异常(因为int
数据类型不能表示结果)。
请注意,所有这三个选项都依赖于平台相关行为:
您的结果可能是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,算术异常中断。)