最近我讨论了有人想像这样检查signed int 溢出if (A + B < 2 * max(A, B))
。让我们暂时忽略逻辑本身是错误的,并在 C/C++ 上下文中讨论有符号整数溢出。 (我相信这完全继承了C标准的这一部分)。
哪些类型的需要有符号整数溢出的检查将被当前的 GCC 优化掉,哪些不会?
由于原文的表述不是那么好,并且显然存在争议,我决定稍微改变一下问题,但将原文保留在下面。
下面使用的所有示例均经过测试 gcc 版本4.7.2 (Debian 4.7.2-5)
并使用编译-O3
也就是说,它是未定义的,GCC 臭名昭著地使用它来执行一些分支简化。我想到的第一个例子是
int i = 1;
while (i > 0){
i *= 2;
}
这会产生无限循环。这种优化的另一种情况是
if (A + 2 < A){
/* Handle potential overflow */
}
其中,假设A
是有符号整型,溢出分支被完全删除。
更有趣的是,有些情况很容易provable整数溢出,保持不变,例如
if (INT_MAX + 1 < 0){
/* You wouldn't write this explicitly, but after static analysis the program
could be shown to contain something like this. */
}
这会触发您所期望的二进制补码表示的分支。同样,此代码使条件分支保持不变
int C = abs(A);
if (A + C < 0){
/* For this to be hit, overflow or underflow had to happen. */
}
现在的问题是,是否存在一种大致类似于if (A + B < C)
or if (A + B < c)
,那会被优化掉吗?当我在写这篇文章之前进行谷歌搜索时,似乎最后一个片段应该被优化掉,但是我无法在不显式使用常量操作的溢出检查中重现这种错误。