这是我的代码
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位,它将改变符号位并用0替换LSB。因此,我认为答案将是-ve和幅度将减1,即-2147483646但它给出的结果为-2。请解释。
这是因为您的计算机使用2补码表示签名值。无符号移位值是0xFFFFFFFE
,它是2补充中的-2,而不是-2147483647
。
移位是在C中定义的实现。
顺便说一下,-2147483647
就是这样的CPU上的0x80000001
。
[expr.shift] / 1
E1 << E2
的值是E1
左移E2
位位置;空位是零填充的。 ...如果E1
具有有符号类型和非负值,并且E1 × 2^E2
可在结果类型的相应无符号类型中表示,则转换为结果类型的该值是结果值;否则,行为未定义。
强调我的。您的程序显示未定义的行为。
编辑:经过仔细考虑,我不再认为它是未定义的行为。 2147483647*2
确实适合unsigned int
,int
的“相应的无符号类型”。它转换为int
并不是未定义的,而只是实现定义的。使用二进制补码定义这种转换的实现是完全合理的,因此2147483647*2 == -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的更多信息。