无符号右移的行为应用于字节变量

考虑以下Java代码片段

byte b=(byte) 0xf1; byte c=(byte)(b>>4); byte d=(byte) (b>>>4); 

输出:

 c=0xff d=0xff 

预期产量:

 c=0x0f 

怎么样? 作为二进制1111 0001 b,无符号右移后0000 1111因此为0x0f但为什么它是0xff如何?

问题是所有参数在转换操作发生之前首先被提升为int

 byte b = (byte) 0xf1; 

b已签名,因此其值为-15。

 byte c = (byte) (b >> 4); 

b首先符号扩展为整数-15 = 0xfffffff1 ,然后向右移动到0xffffffff并通过0xffbyte截断为0xff

 byte d = (byte) (b >>> 4); 

b首先符号扩展为整数-15 = 0xfffffff1 ,然后右移到0x0fffffff并通过0x0fffffff转换为byte截断为0xff

您可以执行(b & 0xff) >>> 4以获得所需的效果。

我猜想b在转移之前是符号扩展到int

所以这可能会按预期工作:

 (byte)((0x000000FF & b)>>4) 

根据Bitwise和Bit Shift运算符 :

无符号右移运算符“>>>”将零移动到最左侧位置,而“>>”之后的最左侧位置取决于符号扩展。

因此,对于b >> 4您将1111 0001转换为1111 1111 (b为负,因此它附加1 ),即0xff

Java试图通过定义两个不同的移位运算符来避免明确支持无符号基本类型。

该问题讨论了无符号右移,但示例同时执行(有符号和无符号),并显示有符号移位(>>)的值。

您的计算适用于无符号移位(>>>)。