在阅读有关程序设计技巧的书时,我看到-0x80000000 + -0x80000000 = 0.这对我没有意义所以我在下面编写了一个快速的C程序来测试,答案确实是0:
#include <stdio.h>
int main()
{
int x = -0x80000000;
int y = -0x80000000;
int z = x + y;
printf("Z is: %d", z);
return 0;
}
任何人都可以解释为什么?我看到有关溢出的内容,但我看不到溢出如何导致0而不是异常或其他错误。我什么都没有警告。
答案 0 :(得分:2)
这里发生的是有符号整数溢出,即undefined behavior,因为没有定义有符号整数的精确表示。
然而,在实践中,大多数机器使用2的有符号整数的补码表示,并且这个特定的程序利用了它。
0x80000000
是无符号整数常量。 -
否定它,将表达式更改为signed。假设您的系统上int
为32位,则此值仍然适合。实际上,它是带符号的32位int
可以容纳的最小值,并且此数字的十六进制表示恰好是0x80000000
。
在2的补码表示中添加数字时,它具有您无需担心符号的功能。它们的添加方式与无符号数字完全相同。
因此,当我们添加x
和y
时,我们会得到:
0x80000000
+ 0x80000000
-------------
0x100000000
因为系统上的int
是32位,所以只保留最低的32位。并且这些位的值为0。
再次注意,这实际上是未定义的行为。它的工作原理是因为你的机器对有符号整数使用2的补码表示,而int
是32位。这对于大多数机器/编译器来说很常见,但不是全部。
答案 1 :(得分:1)
您所看到的是很多实现定义的行为,很可能在运行时触发未定义的行为。如果没有关于你和书籍作家架构的详细信息,就不可能知道。
如果没有其他信息,结果就没有意义。如果您想要一个明确的答案,请参考您的架构的类型范围,并确保分配和算术的结果符合各自的类型。