C++左移运算

C++ left shift operation

这是我的代码

int a=2147483647; 
int b= a<<1;
cout<<"a="<<a<<",  b="<<b;

我得到的输出是- a=214783647, b=-2

a的二进制表示是

0111 1111 1111 1111 1111 1111 1111 1111

通过将其移动 1 位,它将改变符号位并将 LSB 替换为 0。因此,我认为答案将是 -ve,幅度将减去 1,即 -2147483646 但它给出的结果为 -2 。请解释。

嗯,后面的故事很长

由于int是有符号类型,也就是说第一位是符号,整个系统是二补码

所以 x = 0b 1111 1111 1111 1111 1111 1111 1111 0111 是 x = -9 例如 x = 0b 1111 1111 1111 1111 1111 1111 1111 1111 是 x = -1 和 x = 0b 0000 0000 0000 0000 0000 0000 0000 0010 是 2

详细了解 Two complement

[expr.shift]/1 The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. ... if E1 has a signed type and non-negative value, and E1 × 2^E2 is representable in the corresponding unsigned type of the result type, then that value, converted to the result type, is the resulting value; otherwise, the behavior is undefined.

强调我的。您的程序表现出未定义的行为。


编辑:经过仔细考虑,我不再认为这是未定义的行为。 2147483647*2 确实适合 unsigned int、"the corresponding unsigned type" 或 int。它到 int 的转换不是未定义的,而只是实现定义的。对于使用二进制补码的实现来定义此转换是完全合理的,因此 2147483647*2 == -2,只需重新解释位模式,正如其他答案所解释的那样。

这是因为您的计算机对有符号值使用 2 补码。 无符号移位值是 0xFFFFFFFE,即 2 补码中的 -2,而不是 -2147483647.

移位是在 C 中定义的实现。

顺便说一句,-2147483647 在 CPU 上是 0x80000001