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

问题描述 投票:22回答:6

考虑以下Java代码片段

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

输出:

c=0xff
d=0xff

预期产量:

c=0x0f

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

java bit-shift
6个回答
38
投票

问题是所有参数在转换操作发生之前首先被提升为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来获得理想的效果。


4
投票

我猜想b在移位之前会被扩展到int

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

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

1
投票

Bitwise and Bit Shift Operators说:

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

因此,使用b >> 4,你将1111 0001转换为1111 1111(b为负,所以它附加1),这是0xff


0
投票

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

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

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


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类型的值。


-1
投票

字节b =(字节)0xf1;

if(b <0)

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

其他

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

首先,检查值:如果值为负。右转,然后是&0x7F,它将变为正。然后你可以轻松地完成其余的右移(4-1 = 3)。

如果值为正,则使用>> 4或>>> 4进行全部右移。它不会对结果产生任何影响,也不会产生任何右移问题。

© www.soinside.com 2019 - 2024. All rights reserved.