【发布时间】:2021-05-22 19:30:09
【问题描述】:
在阅读 http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html 关于 c 中未定义行为的信息时,我收到了有关此示例的问题。
for (i = 0; i <= N; ++i) { ... }
在这个循环中,编译器可以假设循环会迭代 如果“i”在溢出时未定义,则恰好 N+1 次,这允许 广泛的循环优化可以启动。另一方面,如果 该变量被定义为溢出时环绕,然后编译器 必须假设循环可能是无限的(如果 N 是 INT_MAX) - 然后禁用这些重要的循环优化。 这尤其会影响 64 位平台,因为有这么多代码使用 "int" 作为归纳变量。
这个例子是为了展示 C 编译器可以利用未定义的行为来假设执行时间是精确的 N+1。但我不明白为什么这个假设是有效的。
我可以理解,如果变量被定义为在溢出时环绕并且 N 是 INT_MAX,那么 for 循环将是无限的,因为我将从 0 转到 INT_MAX 并溢出到 INT_MIN,然后循环到 INT_MAX 并从 INT_MIN 重新开始等等。因此编译器无法对执行时间做出这种假设,也无法在这一点上进行优化。
但是如果 i 在溢出时未定义呢?在这种情况下,i 通常从 0 循环到 INT_MAX,然后 i 将被分配 INT_MAX+1,这将溢出到未定义的值,例如 0 和 INT_MAX 之间。如果是这样,条件i<= INT_MAX仍然有效,for循环是否应该不继续并且也是无限的?
【问题讨论】:
-
那么请发音合理。
-
未定义的行为是未定义的。执行具有未定义行为的程序的结果是在您的浴室中产生了一头大象。
-
@EOF:这个问题有充分的理由,唯一的错误是在第三句中,溢出
int将产生一些int值,而不是被允许产生任何行为。 -
没有 INT_MAX+1 就像没有 ∞+1。它从 (int) -MAX 开始。 os.mbed.com/handbook/C-Data-Types
-
@wired:OP 表示
INT_MAX+1,即比INT_MAX大一的数学整数,它确实存在(在任何抽象数存在的意义上)。观察 C 标准本身使用类似的语言;+被定义为产生“操作数之和”,即使存在溢出时不存在这样的和。说明溢出会发生什么的措辞是分开的,即使在同一个子句中也是如此。 OP 在讨论i++如何假设INT_MAX和 1 的总和时做了同样的事情,并分别讨论了在出现这种溢出时会发生什么。
标签: c