给出三个变量:
int x = rand();
int y = rand();
int z = x + y;
z + (~x + 1)
是否等于y
总是如此。或者是否存在可能导致结果不等于y
的溢出?
答案 0 :(得分:6)
在带有回绕的二进制补码签名算术中,(~x + 1)
等于-x
,因此z + (~x + 1)
等于z - x
等于y
,不重要的是x
和y
的原始值。
有两种可能的原因导致C实现可能不会使用带有环绕的二进制补码签名算法。
原则上,C标准仍然提供CPU不使用负数的二进制补码表示的可能性。现在这不太可能具有相关性:UNIVAC是我所知道的唯一仍在生产中的例子,我真的很惊讶地发现 仍处于生产阶段。
C标准说签名溢出有未定义的行为。这意味着允许编译器假设它永远不会发生,并且如果任何一个加法溢出,则生成将产生任意无意义输出(甚至崩溃)的代码。 可能是相关的。
您可以通过将x
,y
和z
声明为unsigned int
而不是int
来避免这两种可能性。然后y + x + (~x + 1)
保证等于y
。