为什么在同一条语句中左移和右移会产生不同的结果?
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 进行算术右移。这是 x 的中间值,以获得 -1 作为输出。
x: 0000 0000 1111 1111
x<<8:1111 1111 0000 0000
x>>8:1111 1111 1111 1111
为什么第一种情况没有出现同样的机制?
您刚刚观察到的是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". 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". Thus, by padding the left side with ones, the negative sign and the value of the original number are maintained.
你一直右移到你的短路变成负数的点,然后当你向后移动时,你得到符号扩展。
第一种情况不会发生这种情况,因为转换不适用于短路。它应用于 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
差异是由两个因素造成的。
C++标准没有规定整数类型的最大值。该标准仅规定了每种整数类型的最小大小。在您的平台上,short
是 16 位值,而 int
s 至少是 32 位值。
第二个因素是two's complement算术
在您的第一个示例中,short
值自然提升为至少 32 位的 int
,因此左移和右移对 int
进行操作, 在转换回 short
.
之前
在您的第二个示例中,在第一次左移操作之后,结果值再次转换回 short
,并且由于二进制补码运算,它最终为负值。右移结束符号扩展负值,导致最终结果 -1.
考虑以下示例:
第一个案例:
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 进行算术右移。这是 x 的中间值,以获得 -1 作为输出。
x: 0000 0000 1111 1111
x<<8:1111 1111 0000 0000
x>>8:1111 1111 1111 1111
为什么第一种情况没有出现同样的机制?
您刚刚观察到的是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". 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". Thus, by padding the left side with ones, the negative sign and the value of the original number are maintained.
你一直右移到你的短路变成负数的点,然后当你向后移动时,你得到符号扩展。
第一种情况不会发生这种情况,因为转换不适用于短路。它应用于 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
差异是由两个因素造成的。
C++标准没有规定整数类型的最大值。该标准仅规定了每种整数类型的最小大小。在您的平台上,
short
是 16 位值,而int
s 至少是 32 位值。第二个因素是two's complement算术
在您的第一个示例中,short
值自然提升为至少 32 位的 int
,因此左移和右移对 int
进行操作, 在转换回 short
.
在您的第二个示例中,在第一次左移操作之后,结果值再次转换回 short
,并且由于二进制补码运算,它最终为负值。右移结束符号扩展负值,导致最终结果 -1.