24

考虑以下java代码片段

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

输出:

c=0xff
d=0xff

预期输出:

c=0x0f

如何?因此,1111 0001 在无符号右移后,二进制中的 b 为 b但为什么会这样 呢?0000 11110x0f0xff

4

6 回答 6

43

问题是所有参数int在移位操作发生之前首先被提升:

byte b = (byte) 0xf1;

b有符号,所以它的值为-15。

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

b首先将符号扩展为整数-15 = 0xfffffff1,然后右移到并被强制转换为0xffffffff截断。0xffbyte

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

b首先将符号扩展为整数-15 = 0xfffffff1,然后右移到并被强制转换为0x0fffffff截断。0xffbyte

你可以做得到(b & 0xff) >>> 4想要的效果。

于 2010-10-16T09:18:02.013 回答
5

我猜这b是转移前的标志int

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

(byte)((0x000000FF & b)>>4)
于 2010-10-16T09:13:48.450 回答
1

根据按位和位移运算符

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

因此,b >> 4您转换1111 00011111 1111(b 为负数,因此它附加1) 即0xff.

于 2010-10-16T09:13:48.963 回答
0

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

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

您的计算对于无符号移位 (>>>) 是正确的。

于 2010-10-16T09:19:01.527 回答
0

字节操作数在移位之前提升为 int。

请参阅https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.19

一元数字提升(第 5.6.1 节)分别对每个操作数执行。(二进制数字提升(第 5.6.2 节)不在操作数上执行。)

https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.1

否则,如果操作数是编译时类型 byte、short 或 char,则通过扩展原语转换(第 5.1.2 节)将其提升为 int 类型的值。

于 2019-02-25T11:59:02.687 回答
-1

字节 b=(字节) 0xf1;

如果 (b<0)

d = (字节) ((字节) ((字节)(b>>1)&(字节)(0x7F)) >>>3);

别的

d = (字节)(b>>>4);

首先,检查值:如果值为负。右移一次,&0x7F,变为正数。然后您可以轻松地进行其余的右移(4-1 = 3)。

If the value is positive, make all right shift with >>4 or >>>4. It does'nt make no difference in result nor any problem of right shift.

于 2019-02-28T06:32:18.007 回答