首页 > 解决方案 > GCC:未定义的溢出行为是否应该保持逻辑一致性?

问题描述

以下代码在我的系统上产生了奇怪的东西:

#include <stdio.h>

void f (int x) {
  int y = x + x;
  int v = !y;
  if (x == (1 << 31))
    printf ("y: %d, !y: %d\n", y, !y);
}

int main () {
  f (1 << 31);
  return 0;
}

编译后-O1,打印出来y: 0, !y: 0

int v现在,除了删除or行会产生预期结果这一令人费解的事实之外if,我对未定义的溢出行为转化为逻辑不一致感到不舒服。

这应该被认为是一个错误,还是 GCC 团队的理念,即一个意外行为可能会级联成逻辑矛盾?

标签: cgccoverflowundefined-behaviorinteger-arithmetic

解决方案


当调用未定义的行为时,任何事情都可能发生。毕竟,它被称为未定义行为是有原因的。

这应该被认为是一个错误,还是 GCC 团队的理念,即一个意外行为可能会级联成逻辑矛盾?

这不是一个错误。我对 GCC 团队的理念了解不多,但总的来说,未定义的行为对于编译器开发人员实现某些优化是“有用的”:假设某些事情永远不会发生,这样优化代码就更容易了。UB之后什么事情都可能发生的原因正是因为这个。编译器做了很多假设,如果其中任何一个被破坏,那么发出的代码就不能被信任。

正如我在另一个答案中所说:

未定义的行为意味着任何事情都可能发生。没有解释为什么在调用未定义的行为后会发生任何奇怪的事情,也不需要. 编译器可以很好地发出 16 位实模式 x86 程序集,产生删除整个主文件夹的二进制文件,发出 Apollo 11 Guidance Computer 程序集代码,或其他任何东西。这不是一个错误。它完全符合标准。


推荐阅读