Java> 有趣的byte及位運算


byte存儲范圍,表示范圍

我們知道byte代表1個字節,數據存儲的范圍:[0x00, 0xFF]。byte變量表示值的范圍:[-128, 127]。

下面這段代碼並不是輸出128,而是輸出-128,因為byte變量表示值的范圍為[-128, 127]。128剛剛好超出上界127有1單位,溢出為-128。
300對應byte值也不是300,而是按byte長度(1字節)截取存儲內容后的值。
可以看到,300 = 0b100101100,截取1byte長度后,值為0b00101100,也就有 b = 0b00101100 => b = 44

byte b = (byte) 128;
System.out.println(b); // 輸出-128

byte b = (byte) 300; // 300 = 0b100101100, b = 0b101100
System.out.println(b); // 輸出44

byte位運算

還有一種比較有意思的現象,就是byte位運算,中間過程是否進行類型轉換,也會影響結果。
請看下面的代碼,分別打印出什么?(i1, i2):

byte a = (byte)0xFF;
int i1 = 0xFF & a;
int i2 = a;

System.out.println(i1); // 打印255
System.out.println(i2); // 打印-1

運行程序,發現打印i1 為255,打印i2為-1,同樣的byte類型變量a = 0xFF,如果直接轉換為int類型,值為-1;如果與0xFF先進行按位與運算,值為255。
中間只是對a和0xFF進行了與運算,而a本身寬1字節,但打印結果卻不同,這是為什么呢?
 
猜測是不是跟運算過程中的類型轉換有關。下面先做驗證:

  1. 全部顯式轉換為byte類型,再 &;
  2. 全部顯式轉換為int類型,再&;
byte a = (byte)0xFF;
int i1 = 0xFF & a;
int i2 = a;
int i3 = (byte)0xFF & (byte)a;
int i4 = (int)0xFF & (int)a;

System.out.println(i1); // 打印255
System.out.println(i2); // 打印-1
System.out.println(i3); // 打印-1
System.out.println(i4); // 打印255

根據打印結果,可以得出結論:

1. byte型數據跟int型數據進行運算時,會先默認轉換為int類型。(類型提升)
2. byte -> int直接類型轉換,並不能改變數的符號。

 
byte型位運算為何結果不同於int型位運算?
int和byte都可以表示負數,為什么轉換為int進行 & ,與轉換為byte進行&,為何結果不一樣?
由結論2,知因為int i4 = (int)0xFF & (int)a;中的類型轉換(int)並不會改變符號,那么是什么時候改變的呢? 只可能是與0xFF進行&時,改變了a的符號。因為結果是255,但byte a = -1,而i2 = a值也是-1。
詳細分析知,0xFF是1byte,而int是2byte。
由於a是int類型,4byte存儲,實際a存儲值 = 補碼(a) = 反碼(-a) + 1 = 反碼(1) + 1 = ~0b0000 0000 0000 0000 0000 0000 0000 0001 + 1 = 0b1111 1111 1111 1111 1111 1111 1111 1111 = 0xFFFF FFFF
可知,

int i4 = 0xFF & (int)a 
   = 0xFF & -1
   = 0xFF & 0xFFFF FFFF 
   = 0xFF,符號位為0,是正數 
=> i4 = 255

不妨將0xFF改成成0xFFFFFFFF,來驗證上面的猜測:

byte a = (byte)0xFF;
...
int i4 = (int)0xFF & (int)a;
int i5 = 0xFFFFFFFF & a;

...
System.out.println(i4); // 打印255
System.out.println(i5); // 輸出-1

可以得到i5 = -1,符合猜測預期。 因此,需要十分注意類型轉換過程中值的變化,還有位寬的變化,特別是涉及到負數,因為計算機中存儲的是補碼,就會涉及到符號位。


免責聲明!

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



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