【发布时间】:2014-08-06 03:06:53
【问题描述】:
例如,给定以下代码:
int f(int n)
{
if (n < 0)
return 0;
n = n + 100;
if (n < 0)
return 0;
return n;
}
假设您传入的数字非常接近整数溢出(距离小于 100),编译器会生成给您负返回的代码吗?
以下是 Simon Tatham 的“The Descent to C”中关于这个问题的摘录:
“GNU C 编译器 (gcc) 会为此函数生成代码,如果您传入(例如)最大可表示的 'int' 值,则该函数可以返回负整数。因为编译器在第一个 if 语句之后知道n 是正数,然后它假设没有发生整数溢出,并使用该假设得出加法后 n 的值必须仍然为正的结论,因此它完全删除了第二个 if 语句并返回未经检查的加法结果。 "
这让我想知道 C++ 编译器中是否存在相同的问题,以及是否应该小心不要跳过整数溢出检查。
【问题讨论】:
-
当您有未定义的行为时,编译器可能会做出看起来很奇怪的假设,但您查看此example here 会看到编译器由于围绕未定义行为的优化而将有限循环变成了无限循环。
-
这里有趣的是,该标准故意将在硬件上(无论如何在所有真实,非虚构硬件上)完全定义好的东西定义为仅未定义的行为所以编译器可以做这种优化。尽管 INT_MAX+1 在您将能够找到的任何 CPU 上确实等于 INT_MIN,但假设它没有并说这是未定义的,您可以合法地优化上述代码或让您考虑将
x+1>x视为“始终正确”,或者让您断言循环迭代是有限的。 -
也许他们觉得这个问题之前已经得到了充分的回答,而我没有很好地搜索到它?
-
@Damon:你这个断言的依据是什么? 1989 年,大多数硬件上的行为是一致的,但不是全部,标准的作者在基本原理中指出,使短无符号值提升为有符号的主要动机因素是,大多数实现都定义了静默环绕溢出语义。
标签: c++ gcc compiler-construction undefined-behavior integer-overflow