为什么Java无符号位移位为负字节是如此奇怪?

时间:2015-04-16 17:49:30

标签: java bit-shift primitive-types

我有一个字节变量:

byte varB = (byte) -1; // binary view: 1111 1111

我希望看到两个最左边的位并执行6位数的 无符号右移

varB = (byte) (varB >>> 6);

但我正在 -1 ,就像它是int类型一样,并且 3 只有我换了30!

我如何解决这个问题并且只能通过6位移位获得结果?

2 个答案:

答案 0 :(得分:8)

原因是与位移时发生的int数字提升相关联的符号扩展。在转移之前,值varB会提升为int。向右转的无符号位移确实会发生,但是在转换回byte时它的效果会被丢弃,而varB (byte) : 11111111 promoted to int : 11111111 11111111 11111111 11111111 shift right 6 : 00000011 11111111 11111111 11111111 cast to byte : 11111111 只保留最后8位:

&

您可以使用按位和运算符0xFF在移位之前屏蔽掉不需要的位。与varB = (byte) ((varB & 0xFF) >>> 6); 进行位操作仅保留8个最低有效位。

varB (byte)     : 11111111
promoted to int : 11111111 11111111 11111111 11111111
bit-and mask    : 00000000 00000000 00000000 11111111
shift right 6   : 00000000 00000000 00000000 00000011
cast to byte    : 00000011

现在发生了什么:

{{1}}

答案 1 :(得分:4)

因为在 {/ 3>}语言中定义了如何移动 for java中的字节。

要点是小于 int 的类型会以静默方式扩展为int,移位然后缩小。

这使您的单行有效地相当于:

byte b = -1;      // 1111_1111
int temp = b;     // 1111_1111_1111_1111_1111_1111_1111_1111
temp >>>= 6;      // 0000_0011_1111_1111_1111_1111_1111_1111
b = (byte) temp;  // 1111_1111

使用无符号语义(仅需要手动缩小转换),仅移动您需要使用无符号语义进行扩展转换所需的字节:

byte b = -1;          // 1111_1111
int temp = b & 0xFF;  // 0000_0000_0000_0000_0000_0000_1111_1111
temp >>>= 6;          // 0000_0000_0000_0000_0000_0000_0000_0011
b = (byte) temp;      // 0000_0011