作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
比如有3个long类型的变量,我们加上a
和 b
得到 s
:
long a, b, s;
...
s = a + b
现在 ((s^a) < 0 && (s^b) < 0)
是做什么的什么意思?
我在 source code 中看到了这样一张支票Python 的:
if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: int + int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
i = a + b;
if ((i^a) < 0 && (i^b) < 0)
goto slow_iadd;
x = PyInt_FromLong(i);
}
最佳答案
这段代码是错误的。
假设有符号整数按位异或的通常 2 的补码规则,则
(s^a) < 0
如果 s
和 a
将它们的符号位设置为相反的值,就会出现这种情况。因此,
((s^a) < 0 && (s^b) < 0)
表示 s
与 a
和 b
的符号不同,它们必须具有等号(假装 0 是正数)。如果你把两个等号的整数相加得到不同符号的结果,那肯定是溢出了,所以这就是溢出检查。
如果我们假设有符号溢出回绕,那么 s
恰好在发生溢出时与 a
和 b
具有相反的符号。但是,有符号溢出是未定义的行为。计算 s
已经是错误的;我们需要在不实际执行操作的情况下检查是否会发生溢出。
Python 不应该这样做。你可以在 Python 2 source code for int.__add__
中看到它应该做什么:
/* casts in the line below avoid undefined behaviour on overflow */
x = (long)((unsigned long)a + b);
if ((x^a) >= 0 || (x^b) >= 0)
它应该转换为 unsigned 以获得定义的溢出行为。由于 issue 7406,在 5 个不同的地方引入了 cast-to-unsigned 修复。在 Python 错误跟踪器上,但看起来他们错过了一个地方,或者 INPLACE_ADD
从那时起就被改变了。我已经在追踪器上留言了。
关于c - 如果和和两个加数的按位异或均为负,这意味着什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31040256/
我是一名优秀的程序员,十分优秀!