c - Gcc 中的大数加法结果(阿贝尔群)

标签 c optimization assembly compiler-construction

我正在阅读有关检测 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);
}

它说它不起作用,因为:

two’s-complement addition forms an abelian group, and so the expression (x+y)-x will evaluate to y regardless of whether or not the addition overflows, and that (x+y)-y will always evaluate to x

这到底是什么意思?这是否意味着C编译器替换sumx+y
为了弄清楚它在说什么,我什至追踪了程序的汇编代码,但没有替换的迹象。

更新:我的问题的本质是,GCC 是否会评估表达式而不计算它?
不是关于补码的问题。
您可以在here中看到示例输出。 .

最佳答案

如果您举一个 4 (0b0100) + 5 (0b0101) 的简单示例,您会发现无符号总和应为 9 (1001),实际上是 -7 以二进制补码表示。如果您随后使用补码算术将该总和 (0b1001) 减去 4:

    0b1001 - 0b0100 = 0b1001 + 2s_complement(0b0100) = 0b1001 + 0b1100 = 0b1_0101 

最终得到 0101,即 5(在 2 的补码运算期间删除溢出的最高有效位 1)。总和减去 5 等于 4:

    0b1001 - 0b0101 = 0b1001 + 2s_complement(0b0101) = 0b1001 + 0b1011 = 0b1_0100

这满足您提供的 C 代码,但仍然导致溢出。

摘自维基百科关于 two's complement 的文章:

Two's complement    Decimal
0111                 7
0110                 6
0101                 5
0100                 4
0011                 3
0010                 2
0001                 1
0000                 0
1111                −1
1110                −2
1101                −3
1100                −4
1011                −5
1010                −6
1001                −7
1000                −8

Update:
To demonstrate your INT_MAX example using my trivial 4 bit integer system with INT_MAX = 7 we can see the same result as your c code.

    7 + 7 (0b0111 + 0b0111) = 0b1110 (-2 in two's complement)

就像上面的例子一样,相减,sum - 7 将等于 7

    0b1110 - 0b0111 = 0b1110 + 2s_complement(0b0111) = 0b1110 + 0b1001 = 0b1_0111

关于c - Gcc 中的大数加法结果(阿贝尔群),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11476410/

相关文章:

一个符合标准的 C 实现#define NULL 可以是古怪的东西吗

ios - 是否在运行时生成图像?

java - 网络爬虫,反馈?

gcc - 使用Cygwin gcc编译+链接自定义操作系统:无法识别的仿真模式:elf_i386

c - 错误(DCC :1086):redeclaration of uint16_t

c - 使用 scanf() 获取的整数在 C 中未获得其预期值

c - 为什么 strlen 的 REPNE SCASB 实现有效?

考虑下面的源代码,其中 N 是用 #define 声明的常量

c - 如何返回多个值并将它们存储在 main() 函数中?

mysql - SUM(val/2) 和 SUM(val)/2 哪个更好?