简体   繁体   English

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

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

Consider the following Example: 请考虑以下示例:

First Case: 第一个案例:

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

Second Case: 第二种情况:

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

The output in the first case is 255 whereas in the second case is -1. 第一种情况下的输出是255,而第二种情况下的输出是-1。 -1 as output does makes sense as cpp does a arithmetic right shift. -1因为输出确实有意义,因为cpp进行算术右移。 Here are the intermediate values of x to obtain -1 as output. 以下是获取-1作为输出的x的中间值。

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

Why doesn't the same mechanism happen in the first case? 为什么在第一种情况下不会发生相同的机制?

The difference is a result of two factors. 差异是两个因素的结果。

  1. The C++ standard does not specify the maximum values of integral types. C ++标准没有指定整数类型的最大值。 The standard only specifies the minimum size of each integer type. 标准仅指定每个整数类型的最小大小。 On your platform, a short is a 16 bit value, and an int s is at least a 32 bit value. 在您的平台上, short是16位值, int s至少是32位值。

  2. The second factor is two's complement arithmetic. 第二个因素是二进制补码算法。

In your first example, the short value is naturally promoted to an int , which is at least 32 bits, so the left and the right shift operates on an int , before getting converted back to a short . 在你的第一个例子中, short值自然地被提升为int ,它至少是32位,所以左移和右移在int ,然后转换回short

In your second example, after the first left shift operation the resulting value is once again converted back to a short , and due to two's complement arithmetic, it ends up being a negative value. 在第二个示例中,在第一个左移位操作之后,结果值再次转换回short ,并且由于二进制补码算法,它最终为负值。 The right shift ends up sign-extending the negative value, resulting in the final result of -1. 右移最终符号扩展负值,最终结果为-1。

What you just observed is sign extension : 您刚观察到的是符号扩展

Sign extension is the operation, in computer arithmetic, of increasing the number of bits of a binary number while preserving the number's sign (positive/negative) and value. 符号扩展是计算机算术中增加二进制数的位数同时保留数字符号(正/负)和值的操作。 This is done by appending digits to the most significant side of the number, following a procedure dependent on the particular signed number representation used. 这是通过在依赖于所使用的特定签名数字表示的过程之后将数字附加到数字的最重要的一侧来完成的。

For example, if six bits are used to represent the number "00 1010" (decimal positive 10) and the sign extend operation increases the word length to 16 bits, then the new representation is simply "0000 0000 0000 1010". 例如,如果使用六位来表示数字“001010”(十进制正10)并且符号扩展操作将字长增加到16位,则新表示仅为“0000 0000 0000 1010”。 Thus, both the value and the fact that the value was positive are maintained. 因此,保持价值和价值为正的事实。

If ten bits are used to represent the value "11 1111 0001" (decimal negative 15) using two's complement, and this is sign extended to 16 bits, the new representation is "1111 1111 1111 0001". 如果使用十位来表示使用二进制补码的值“11 1111 0001”(十进制负15),并且这是符号扩展到16位,则新表示为“1111 1111 1111 0001”。 Thus, by padding the left side with ones, the negative sign and the value of the original number are maintained. 因此,通过用左边填充左边,保持负号和原始数值。

You rigt shift all the way to the point where your short becomes negative, and when you then shift back, you get the sign extension. 您必须一直转移到您的空头变为负数的位置,然后当您转回时,您将获得符号扩展。

This doesn't happen in the first case, as the shift isn't applied to a short. 在第一种情况下不会发生这种情况,因为转移不适用于短期。 It's applied to 255 which isn't a short, but the default integral type (probably an int ). 它应用于255 ,这不是短,但默认的整数类型(可能是一个int )。 It only gets casted after it's already been shifted back: 只有在它已经被移回后它才被铸造:

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