簡體   English   中英

Java bithift陌生

[英]Java bitshift strangeness

Java有兩個用於右移的位移操作符:

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

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

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html

這看起來相當簡單,所以任何人都可以向我解釋為什么這個代碼,當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

IE瀏覽器。 1s而不是零被移動到左側位置

這是因為&實際上正在對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的任何東西。 所以,你的按位移位和&隱式地將值轉換為背景中的int ,然后通過外部顯式轉換返回到byte 最后一次轉換消除了較高位中的零。

要獲得您期望的結果,請嘗試在int上執行此操作。

其他人告訴你為什么,但我會進一步分解並提供真正問題的答案。

byte foo = (byte)((bar & ((byte)-64)) >>> 6);

由於&運算符會將所有內容提升為int,因此它的作用基本上是:

byte foo = (byte)(((int)bar & (int)((byte)-64)) >>> 6);

如果bar是-128那么(int)bar是0xFFFFFF80然后用0xFFFFFFC0編輯...這是:0xFFFFFF80,然后你向右移動6位得到:0x3FFFFFFE

正確的答案很簡單:

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

bar被提升為&操作的int,因此int中唯一剩下的就是原始字節的前兩位。 然后將其右移6位並將其轉換回字節。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM