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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3948220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:05:18  来源:igfitidea点击:

Behaviour of unsigned right shift applied to byte variable

javabit-shift

提问by Radheshyam Nayak

Consider the following snip of java code

考虑下面的java代码片段

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

output:

输出:

c=0xff
d=0xff

expected output:

预期输出:

c=0x0f

how? as b in binary 1111 0001after unsigned right shift 0000 1111hence 0x0fbut why is it 0xffhow?

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

回答by starblue

The problem is that all arguments are first promoted to intbefore the shift operation takes place:

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

byte b = (byte) 0xf1;

bis signed, so its value is -15.

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

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

bis first sign-extended to the integer -15 = 0xfffffff1, then shifted right to 0xffffffffand truncated to 0xffby the cast to byte.

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

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

bis first sign-extended to the integer -15 = 0xfffffff1, then shifted right to 0x0fffffffand truncated to 0xffby the cast to byte.

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

You can do (b & 0xff) >>> 4to get the desired effect.

您可以这样做(b & 0xff) >>> 4以获得所需的效果。

回答by CodesInChaos

I'd guess that bis sign extended to intbefore shifting.

我猜这bint在转移之前扩展到的符号。

So this might work as expected:

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

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

回答by Progman

According to Bitwise and Bit Shift Operators:

根据按位和位移运算符

The unsigned right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost position after ">>" depends on sign extension.

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

So with b >> 4you transform 1111 0001to 1111 1111(b is negative, so it appends 1) which is 0xff.

所以随着b >> 4你转换1111 00011111 1111(b 是负数,所以它附加1) 是0xff

回答by soru

Java tries to skimp on having explicit support for unsigned basic types by defining the two different shift operators instead.

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

The question talks about unsigned right shift, but the examples does both (signed and unsigned), and shows the value of the signed shift (>>).

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

Your calculations would be right for unsigned shift (>>>).

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

回答by Joe23

The byte operand is promoted to an int before the shift.

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

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

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

Unary numeric promotion (§5.6.1) is performed on each operand separately. (Binary numeric promotion (§5.6.2) is not performed on the operands.)

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

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

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

Otherwise, if the operand is of compile-time type byte, short, or char, it is promoted to a value of type int by a widening primitive conversion (§5.1.2).

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

回答by user3898882

byte b=(byte) 0xf1;

字节b=(字节)0xf1;

if (b<0)

如果 (b<0)

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

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

else

别的

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

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

First, check the value: If the value is negative. Make one right shift, then & 0x7F, It will be changed to positive. then you can make the rest of right shift (4-1=3) easily.

首先,检查值:如果值为负。右移一格,然后&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.

如果值为正,则用 >>4 或 >>>4 右移。它对结果没有任何影响,也没有任何右移问题。