繁体   English   中英

为什么同一语句中的左移和右移会产生不同的结果?

[英]Why does left shift and right shift in the same statement yields a different result?

请考虑以下示例:

第一个案例:

short x=255;
x = (x<<8)>>8;
cout<<x<<endl;

第二种情况:

short x=255;
x = x<<8;
x = x>>8;
cout<<x<<endl;

第一种情况下的输出是255,而第二种情况下的输出是-1。 -1因为输出确实有意义,因为cpp进行算术右移。 以下是获取-1作为输出的x的中间值。

x: 0000 0000 1111 1111  
x<<8:1111 1111 0000 0000 
x>>8:1111 1111 1111 1111

为什么在第一种情况下不会发生相同的机制?

差异是两个因素的结果。

  1. C ++标准没有指定整数类型的最大值。 标准仅指定每个整数类型的最小大小。 在您的平台上, short是16位值, int s至少是32位值。

  2. 第二个因素是二进制补码算法。

在你的第一个例子中, short值自然地被提升为int ,它至少是32位,所以左移和右移在int ,然后转换回short

在第二个示例中,在第一个左移位操作之后,结果值再次转换回short ,并且由于二进制补码算法,它最终为负值。 右移最终符号扩展负值,最终结果为-1。

您刚观察到的是符号扩展

符号扩展是计算机算术中增加二进制数的位数同时保留数字符号(正/负)和值的操作。 这是通过在依赖于所使用的特定签名数字表示的过程之后将数字附加到数字的最重要的一侧来完成的。

例如,如果使用六位来表示数字“001010”(十进制正10)并且符号扩展操作将字长增加到16位,则新表示仅为“0000 0000 0000 1010”。 因此,保持价值和价值为正的事实。

如果使用十位来表示使用二进制补码的值“11 1111 0001”(十进制负15),并且这是符号扩展到16位,则新表示为“1111 1111 1111 0001”。 因此,通过用左边填充左边,保持负号和原始数值。

您必须一直转移到您的空头变为负数的位置,然后当您转回时,您将获得符号扩展。

在第一种情况下不会发生这种情况,因为转移不适用于短期。 它应用于255 ,这不是短,但默认的整数类型(可能是一个int )。 只有在它已经被移回后它才被铸造:

on the stack:     0000 0000 0000 0000 0000 0000 1111 1111
<<8
on the stack:     0000 0000 0000 0000 1111 1111 0000 0000
>>8
on the stack:     0000 0000 0000 0000 0000 0000 1111 1111
convert to short: 0000 0000 1111 1111

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM