这是我的代码
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。请解释。
答案 0 :(得分:2)
[expr.shift] / 1 :
E1 << E2
的值是E1
左移E2
位的位置;空出的位为零。 ...如果E1
具有带符号的类型且非负值,并且E1 × 2^E2
在结果类型的对应的无符号类型中可表示,则将结果转换为结果类型值;否则,行为是不确定的。
强调我的。您的程序表现出未定义的行为。
编辑:经过仔细考虑,我不再认为这是未定义的行为。 2147483647*2
确实适合unsigned int
的{{1}},即“相应的无符号类型”。它到int
的转换不是不确定的,而仅仅是实现定义的。对于使用二进制补码的实现来定义此转换是完全合理的,以便int
仅重新解释位模式,如其他答案所述。
答案 1 :(得分:2)
这是因为您的计算机对符号值使用2补码。
无符号移位值为0xFFFFFFFE
,即2补码中的-2,不是-2147483647
。
移位是用C定义的实现。
顺便说一句,-2147483647
在这种CPU上是0x80000001
。
答案 2 :(得分:1)
好吧,背后还有很长的故事。
因为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 000000是2
详细了解Two complement。