【发布时间】:2019-09-01 01:37:36
【问题描述】:
如下图,代码有bug。当输入 a = -1, b = 1 时,其中一行出现运行时错误。您能帮我理解 (a & b) 是如何变成 INT_MIN 的吗?
在我的理解中,-1 表示为 32 位二进制格式 0xFFFFFFFF,1 表示为 32 位格式 0x00000001,因此 (-1 & 1) 将变为 0x00000001。我的 python 命令也显示 '0b1' 作为结果。为什么会报INT_MIN的错误?
int getSum(int a, int b) {
while (b != 0) {
int carry = (a & b) << 1;//BUG! left shift of negative value -2147483648
a = a ^ b;
b = carry;
}
return a;
}
更新:负数的右移是否定义明确?只要满足下面引用的要求,右移负数似乎是可以的。
来自 cppreference.com,
对于无符号 a 和有符号 a 具有非负值,值 a >> b 是 a/2b 的整数部分。对于负 a,a 的值 >> b 是实现定义的(在大多数实现中,这执行 算术右移,因此结果仍然为负)。
在任何情况下,如果右操作数的值为负数或 大于或等于提升的左操作数中的位数, 行为未定义。
【问题讨论】:
-
我们知道用二进制表示负数的方式不止一种,而不仅仅是 0xFFFFFFFF en.wikipedia.org/wiki/Signed_number_representations
-
请注意,XOR 不会产生比操作数更多的位,因此它永远不会溢出(可能在具有陷阱表示的系统上除外)Can XOR of two integers go out of bounds?。 INT_MIT 在
int的范围内,因此它不是溢出 -
第一个
a & b是1如您所说,但您处于更新a和b值的while循环中,该错误出现在稍后的迭代中 -
在 C 中使用 unsigned types 进行位旋转。
标签: c bit-manipulation