对常量和变量执行除法运算有什么区别

时间:2017-06-23 13:22:01

标签: c variables gcc constants integer-division

根据此link,执行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。

在完成所有这些实验之后,我注意到直接对常数进行除法运算的结果与对变量进行除法运算的结果不同。那究竟是什么让这个与众不同?

1 个答案:

答案 0 :(得分:5)

根据标准,两种结果均可接受。 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)