Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java位移位奇异性_Java_Debugging_Bit Shift - Fatal编程技术网

Java位移位奇异性

Java位移位奇异性,java,debugging,bit-shift,Java,Debugging,Bit Shift,Java有2个用于右移的位移位运算符: >> shifts right, and is dependant on the sign bit for the sign of the result >>> shifts right and shifts a zero into leftmost bits 这似乎相当简单,所以有人能向我解释一下,为什么这段代码,当bar的值为-128时,foo的值为-2: byte foo = (byte)((bar & (

Java有2个用于右移的位移位运算符:

>> shifts right, and is dependant on the sign bit for the sign of the result

>>> shifts right and shifts a zero into leftmost bits

这似乎相当简单,所以有人能向我解释一下,为什么这段代码,当bar的值为-128时,foo的值为-2:

byte foo = (byte)((bar & ((byte)-64)) >>> 6);
这意味着要做的是取一个8位字节,屏蔽最左边的2位,然后将它们移到最右边的2位。即:

initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b10000000
0b10000000 >>> 6 = 0b00000010
结果实际上是-2,也就是

0b11111110

也就是说,1而不是0被移到左边的位置,这是因为&实际上正在执行升级到
int
——这会留下大量的“1”位。然后右移,将最左边的2位保留为0,但通过返回字节忽略最左边的位

当您分离出以下操作时,这一点变得更加清楚:

public class Test
{
    public static void main(String[] args)
    {
        byte bar = -128;
        int tmp = (bar & ((byte)-64)) >>> 6;
        byte foo = (byte)tmp;
        System.out.println(tmp);
        System.out.println(foo);
    }
}
印刷品

67108862
-2
因此,要再次执行位算术:

initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b11111111111111111111111110000000 // it's an int now
0b10000000 >>> 6 = 0b00111111111111111111111111100000 // note zero-padding
(byte) (0b10000000 >>> 6) = 11100000 // -2
即使从&运算中得到正确的结果(通过在该点强制转换),
>
仍会将第一个操作数提升为
int
第一个操作数

编辑:解决方案是改变遮罩的方式。不是通过-64屏蔽,而是通过128+64=192=0xc0屏蔽:

byte foo = (byte)((bar & 0xc0) >>> 6);

这样你就只剩下你想要的两位了,而不是在最重要的24位上有一个1的负载。

AFAIK,在Java中,大多数操作符(+、-、>>,等等)不能处理小于
int
s的任何东西。因此,按位移位和
&
在后台将值隐式转换为
int
,然后通过显式转换返回到
字节。最后一次强制转换去掉高位中的零


要获得您期望的结果,请尝试在
int
s上执行此操作。

其他人已经告诉您原因,但我将进一步细分,并提供真正问题的答案

byte foo = (byte)((bar & ((byte)-64)) >>> 6);
由于&operator会将所有内容提升为int,因此这实际上是:

byte foo = (byte)(((int)bar & (int)((byte)-64)) >>> 6);
如果条为-128,则(int)条为0xFFFF80,然后与0xFFFFC0进行&'。。。也就是:0xFFFF80,然后向右移动6个位置,得到:0x3FFFFFFE

正确的答案非常简单:

byte foo = (byte)((bar & 0xC0) >> 6);

对于&操作,bar被提升为int,因此该int中只剩下原始字节的前两位。然后将其右移6位,并将其转换回字节。

@Martin:不,因为移位也会起到提升作用。将在一分钟内使用解决方案进行编辑。非常感谢,显然您的bitfoo比我的大;)注意,此处不需要>>>,因为符号位已被清除。另外,最初的海报需要顶部的两位,即0xC0。你说0xC0,Jon说0xD0。我想我必须在这里检查你的逻辑…@Martin:0xC0是正确的。我已经确定了我的答案。多么尴尬:)我开始得出那个结论,我开始三次检查它,从不怀疑伟大的双向飞碟