Java byte位移操作 注意事項


Java對byte 的 + - * / >> >>> << & | ^ (加,減,乘,除,右移,左移,無符號右移,位與,位或,位異或)操作,均會是首先將byte轉化為int, 再行運算。這一事實可能導致多種問題:

 
 
假設我們想進行如下byte運算: 1111 1000 右移1位,再與0000 0001 或運算,得 0111 1101。
直覺寫程序如下:
byte b = 0xf8;
byte b2 =  b >> 1 | 0x01;  
 
這個寫法里有多重錯誤,現逐個糾正:
1 編譯器報錯,int無法直接自動轉化為byte 
為解決此問題,加強制轉化。
byte b = (byte)0xf8;
byte b2 = (byte)( (b >> 1) | 0x01);   
 
 
2 輸出為 1111 1101 不是我們想要的 0011 1101
原因是>> 是有符號右移,當符號位為1時,左側補的是1而非0。
修改為使用 >>> 無符號右移:
byte b = (byte)0xf8;
byte b2 = (byte)( (b >>> 1) | 0x01);  
 
3 運行后發現輸出依然為 1111 1101 
原因是byte在運算前先轉化為int再行位運算,因此分解后的運算步驟如下:
b 轉化為int  1111 1000 轉化為      11111111 11111111 11111111 11111000
無符號右移1位                      01111111 11111111 11111111 11111100
與 0x01 按位或                  01111111 11111111 11111111 11111101
強制轉化回byte     11111101
解決方案,在右移運算前先 位與 0xff
byte b = (byte)0xf8;
byte b2 = (byte)( ((b & 0xff )>>> 1) | 0x01);  //注意必須加括號,因為 >>> 的優先級高於 &
 
 
4 運行后發現輸出為我們想要的結果  0111 1101。運算步驟分解如下:
b 轉化為int  1111 1000 轉化為   11111111 11111111 11111111 11111000
和0xff 進行 & 操作              00000000 00000000 00000000 11111000
無符號右移1位   00000000 00000000 00000000 01111100
與 0x01 按位或  00000000 00000000 00000000 01111101
強制轉化回byte  01111101
 
 
 
5 關於System.out.println();
byte b = (byte)0xf8;
System.out.println(b);   --最終輸出為-8
運算步驟為:
b 轉化為int  1111 1000 轉化為   11111111 11111111 11111111 11111000
取符號位 -                      -1111111 11111111 11111111 11111000
取返+1(因為是按補碼運算)      -0000000 00000000 00000000 00001000
輸出  -8
 
 
 
 
 
最終結論:
1 區分使用 >> 和 >>>
2 在 >> 操作前要首先 & 0xff
3 注意符號優先級,正確使用括號。
4 需要強烈注意的一點是 & 的優先級小於 + . 因此 a = b & 0xff + 2000 的結果 可能不是你想要的
 
 
 
 
 
 
附:
打印byte,int 每個bit值的函數。
 
public static void printByte(byte b){
    for(int i = 7; i >=0 ; i --){
        int shiftleft = (b >> i) & 0x01;
        System.out.print(shiftleft);
    }
    System.out.println();
}
 
public static void printInt(int b){
    for(int i = 31; i >=0 ; i --){
        int shiftleft = (b >> i) & 0x01;
        System.out.print(shiftleft);
    }
    System.out.println();
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM