C-在常数和变量上执行划分操作有什么区别?



根据此链接,执行INT_MIN/-1除法操作将导致该程序在i386 CPU中终止。我的处理器具有32位体系结构,我使用GCC编译器。我已经进行了以下实验来检查它。

int a = INT_MIN;
int b = -1;
int c = a / b;
printf("%dn",c);

根据上面提到的链接中指定的信息,该程序终止抛出浮点异常。但是当我以不同的方式尝试时,情况并不相同。


int c = INT_MIN / -1;
printf("%dn",c);  

编译该程序后,编译器抛出了以下警告。

iso.c:在函数" main"中:
ISO.C:6:18:警告:表达式的整数溢出[-Woverflow]
int c = int_min/-1;
_____________^

但我得到了输出-2147483648。我再次做了更多两个实验。


int a = INT_MIN;
int b = -1;
printf("%dn",a / b);

这是一个浮点例外。


printf("%dn",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/-1INT_MAX + 1,因此该操作调用不确定的行为,因此任何结果(包括崩溃(都是可接受的

正如 @tilz0r在他的评论中所解释的那样,当值以变量传递时,操作将在运行时执行并升高一个sigfpe信号。但是,当操作仅涉及编译时常数时,该操作由编译器时间由编译器执行。在GCC实施中,编译器保护自身免受错误的影响,并仅对INT_MAX + 1使用最佳代表。在32位2的补充实现中,int_max为0x7fffffff,因此int_max 1是(签名溢出后(0x80000000或int_min再次(-2147483648(

最新更新