根据此链接,执行 INT_MIN / -1 除法运算将导致程序在 i386 CPU 中终止。我的处理器是 32 位架构,我使用 GCC 编译器。我做了以下实验来检查它。
int a = INT_MIN;
int b = -1;
int c = a / b;
printf("%d\n",c);
根据上面提到的链接中指定的信息,该程序终止并抛出浮点异常。但是当我以不同的方式尝试时,情况就不一样了。
int c = INT_MIN / -1;
printf("%d\n",c);
编译器在编译此程序后抛出以下警告。
iso.c:在函数“main”中:
iso.c:6:18:警告:表达式中的整数溢出 [-Woverflow]
int c = INT_MIN / -1;
_____________^
但我得到了输出 -2147483648。我再一次做了两个实验。
int a = INT_MIN;
int b = -1;
printf("%d\n",a / b);
这是一个浮点异常。
printf("%d\n",INT_MIN / -1);
这引发了以下编译器警告。
iso.c:在函数“main”中:
iso.c:6:24:警告:表达式中整数溢出 [-Woverflow]
printf("%d\n",INT_MIN / -1);
__________________^
而这个程序的输出又是-2147483648。
在做了所有这些实验之后,我注意到直接对常量进行除法运算的结果与对变量进行除法运算的结果不同。那么究竟是什么造成了这种差异呢?
根据标准,这两个结果都是可接受的。C99 的 n1256 草案说(强调我的):
6.5 表达式
...
5 如果在表达式求值过程中出现异常情况(即,如果结果未在数学上定义或不在其类型的可表示值范围内),则行为未定义。
在2的补码整数表示,INT_MIN/-1
是INT_MAX + 1
这样的动作调用未定义行为,所以任何结果(包括崩溃)是可以接受的
正如@tilz0R 在他的评论中所解释的,当值在变量中传递时,操作在运行时执行并引发 SIGFPE 信号。但是当操作只涉及编译时常量时,该操作由编译器在编译时执行。在 gcc 实现中,编译器保护自己免受错误的影响,并简单地将其最佳表示用于INT_MAX + 1
. 在 32 位 2 的补码实现中,INT_MAX 是 0x7fffffff,所以 INT_MAX + 1 是(有符号溢出后)0x80000000 或 INT_MIN (-2147483648)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句