Java的无符号移位右(>>>)是有符号移位

时间:2020-02-17 21:52:46

标签: java

我正尝试向右移位,以便将某些位与字节隔离,因此我希望进行无符号移位,据我的理解,“新”位应为零。但是,我发现在测试中>>>与>>没有什么区别。 -128 >> 4 = -8如预期,但-128 >>> 4应该为8,但我仍然为-8。

byte data = (byte)-128;
System.out.println((byte)(data >>> 4));
System.out.println((byte)(data >> 4));

感谢您的帮助。

2 个答案:

答案 0 :(得分:7)

无符号右移运算符确实在此代码中执行无符号右移;由于从byteint的隐式转换,它只是被隐藏了。说Java语言规范(§15.19):

运算符<<(左移),>>(有符号右移)和>>>(无符号右移)称为移位运算符。移位运算符的左操作数是要移位的值;右侧操作数指定移位距离。 [...]对每个操作数分别执行一元数值提升(第5.6.1节)。

一元数字促销表示(§5.6.1):

[...]如果操作数是编译时类型byteshortchar,则将其提升为int类型的值不断扩大的原始转换(第5.1.2节)。

因此,您的代码的评估如下:

  • 作为byte的左操作数的-128>>>被提升为int的值-128,即0b11111111111111111111111110000000二进制。
  • 对此int值进行无符号右移,结果为268435448,二进制形式为0b00001111111111111111111111111000。请注意,最左边的四个位为零,就像您从无符号右移中所期望的那样。
  • 然后将该结果显式转换为(byte),得到结果-8

使用REPL:

> byte b = -128;
> int shifted = b >>> 4;
> shifted
268435448
> (byte) shifted
-8

对于所需的行为,可以使用& 0xFF进行从byteint的“无符号”转换:

> ((b & 0xFF) >>> 4)
8

答案 1 :(得分:1)

有符号的右移运算符'>>'使用符号位填充尾随位置,而无符号的右移运算符'>>'不使用符号位填充尾随位置。它总是以0s填充尾随位置