1

考虑以下 C 程序:

#include <limits.h>

int main() {
  int x = INT_MIN;
  int y = -x;
  return y;
}

该程序具有未定义的行为,因为 INT_MIN 的否定是不可表示的;或者,成为一名语言律师——因为 C 标准是这样说的。

现在,编译器知道或者可以知道,情况就是这样。然而 - GCC 和 clang 都没有对此发出警告,即使使用-W -Wall -Wextra(GodBolt); 只有清理未定义的行为才能捕获它 - 在运行时。

为什么会这样?通常,试图证明 UB 发生在编译时是否成本太高,所以编译器不会打扰?

4

1 回答 1

-1

当使用某些实现或配置时,这样的构造将是安全的。当使用启用优化但未启用优化的 clang 或 gcc 时-fwrapv,此类构造可能会导致其他地方的代码以不受普通因果律约束的方式进行无意义的处理。

用 C 标准的话来说,代码是不可移植的或错误的。从已发布的基本原理中,很明显该标准旨在该短语包括不可移植但正确的构造当用于在旨在适合低级编程的实现上执行低级任务时。然而,该标准给予编译器编写者,其客户不会故意将此类结构用于低级编程,在这种情况下,他们可以自由地将它们视为“错误”,而不是假定它们是故意但不可移植的。希望将他们的编译器出售给将要使用它们的程序员的人比委员会更能知道他们的客户会故意使用哪些结构,因此没有必要让标准本身做出这样的区分。

然而,一些不受此类市场压力影响的编译器在不同的理念下运行,其中“不可移植或错误”一词的意思是“不可移植,因此是错误的”。因此,即使在整数溢出永远不会在机器代码级别产生任何副作用的平台上,这样的编译器有时也会在它们确定整数溢出不可避免的情况下不做有意义的行为,即使没有任何方面否则程序行为对计算结果有任何因果关系。

于 2021-08-03T15:42:03.563 回答