【发布时间】:2012-07-13 18:41:04
【问题描述】:
我正在阅读有关在 C 中检测溢出的技术。显示检测溢出的错误解决方案的示例之一是:
/* Determine whether arguments can be added without overflow */
int tadd_ok(int x, int y) {
int sum = x+y;
return (sum-x == y) && (sum-y == x);
}
它说它不起作用,因为:
二的补码加法形成一个阿贝尔群,因此 表达式 (x+y)-x 将计算为 y 而不管是否 加法溢出,并且 (x+y)-y 将始终计算为 x
这到底是什么意思?这是否意味着C编译器将sum替换为x+y?
为了弄清楚它在说什么,我什至跟踪了程序的汇编代码,但没有替换的迹象。
更新:我的问题的本质是,GCC 是否在不计算表达式的情况下评估它?
这不是关于二进制补码的问题。
您可以在here 中看到示例输出。
【问题讨论】:
-
“阿贝尔群”只是“环”的一个花哨的数学术语。具有通常溢出行为的二进制补码整数形成整数“环”。当你加/减时,你沿着环移动。因此,无论溢出如何,您都可以随时向相反方向移动。
-
你的意思是说,看到有符号溢出给出了未指定的结果,这种“损坏的溢出检测方法”可能由于使用未指定的优化而意外地起作用?
-
@ArashThr:那我不确定你在这里问什么!编译器可以简化算术表达式,但他们没有必须这样做。我不确定这与阿贝尔群有什么关系。
-
正如 Oli 所说,它们不是必需的或强制的,但是自从您询问 gcc 以来,它通常会这样做,而且我已经看到它用一个结果替换了许多代码行和一个很长的循环。因为它都是静态的东西,它预先计算了结果并简单地用结果填充寄存器,删除了大量的代码。
-
问题更新值得更改标题、标签和更好的措辞,因为问题开始谈论 2 的补码溢出并最终询问 gcc 行为。
标签: c optimization assembly compiler-construction