1 c variables gcc constants integer-division
根据此链接,执行INT_MIN/-1除法运算将导致程序在i386 CPU中终止.我的处理器是32位架构,我使用GCC编译器.我做了以下实验来检查它.
int a = INT_MIN;
int b = -1;
int c = a / b;
printf("%d\n",c);
Run Code Online (Sandbox Code Playgroud)
根据上面提到的链接中指定的信息,该程序终止抛出浮点异常.但是当我以不同的方式尝试它时,情况就不一样了.
int c = INT_MIN / -1;
printf("%d\n",c);
Run Code Online (Sandbox Code Playgroud)
编译此程序后,编译器发出以下警告.
iso.c:在函数'main'中:
iso.c:6:18:warning:表达式中的整数溢出[-Woverflow]
int c = INT_MIN/-1;
_____________ ^
但我得到了输出-2147483648.我再次做了两次实验.
int a = INT_MIN;
int b = -1;
printf("%d\n",a / b);
Run Code Online (Sandbox Code Playgroud)
这是一个浮点异常.
printf("%d\n",INT_MIN / -1);
Run Code Online (Sandbox Code Playgroud)
这引发了以下编译器警告.
iso.c:在函数'main'中:
iso.c:6:24:warning:表达式中的整数溢出[-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)