參考:https://blog.csdn.net/iamgamer/article/details/79354617
其中有兩個位運算,一個是>>,一個是&。
0xff的作用一:
十六進制0xff的長度是一個字節,即八位,二進制為:1111 1111,那么一個 8bit 數與1111 1111與運算還是這個數本身,但是一個16bit 數與 0xff就被截斷了,比如 1100110011001100 & 0xff結果為 11001100。那如果想不被截斷怎么辦?把0xff擴展為二個字節即:0xffff,那么以此類推,0xffffff,0xffffffff都出來了。
0xff的作用二:
java專屬,由於java沒有unsigned類型,所以為了適應與其他語言二進制通訊時各種數據的一致性,需要做一些處理。
最直觀的例子:int a = -127 & 0xFF ; // 等同於 unsigned int c = 129; (這里的-127與129是字節,只為了直觀而寫的具體數字)
這里要嚴格說明一點:再32位機器上,0xff實際上是 0x00000000 00000000 00000000 11111111,
而-127是 11111111 11111111 11111111 10000001 (補碼形式), 那么-127 & 0xff的結果自然是
00000000 00000000 00000000 10000001 即 129.
簡而言之,該作用主要是為了將 有符號數轉換為無符號數。
>>8的作用:
這個是根據需求而定的,可以是>>8也可以是>>16,>>24,等等
而跟 & 0xff運算的意義其實就是截斷,將123456的高位右移8位,通過0xff截取出來。實際意義就是取字節,比如一個4字節的數,需要將每個字節內容取出來轉換出目標數據,那么通過>> 並且 &0xff 運算 就可以去除想要的部分。
再詳細點:4字節 ,32 位,按照大端方式排列,
最高位 最低位
11111111 10101010 11000011 10101010
最高位8字節要移到最低位那么,這個8個字節>>(3*8),然后與0xff運算,取出,然后后續得>>(2*8) & 0xff ;>>(1*8) & 0xff,均可取出。
再來一個簡單的例子鞏固基礎:
int a = 1234567890; byte b1[] = new byte[4]; // b1[0] = (byte) (a & 0xff); // b1[1] = (byte)((a >> 8) & 0xff); // b1[2] = (byte)((a >> 16) & 0xff); // b1[3] = (byte)((a >> 24) & 0xff); b1[0] = (byte)((a >> 24) & 0xff); b1[1] = (byte)((a >> 16) & 0xff); b1[2] = (byte)((a >> 8) & 0xff); b1[3] = (byte) (a & 0xff); int b2 = (b1[0]& 0xff) <<24 | (b1[1] & 0xff)<<16 | (b1[2] &0xff)<<8| (b1[3]& 0xff); int b3 = (b1[0]) <<24 | (b1[1])<<16 | (b1[2])<<8| (b1[3]); System.out.println(b2);//正確結果 System.out.println(b3);//錯誤結果,沒有做有符號轉無符號操作,導致結果不對。
將int a轉換成字節,一般情況下,int 4字節,那么需要4個byte來保存,又因為java是大端排序,那么byte[0]為最高位,所以需要>>24,這么一個個的把a的4個字節取出存入byte數組中,這里0xff不僅截斷,而且還將有符號轉換成了無符號。
那么將字節轉換回去就不一樣了,不是截斷而是融合 ,因此需要將& 改為 |,並且還得把每個字節移到所在實際位置,比如byte[0]是最高位,因此還得將其移到4個字節的頭部即需要<<24,那么后續得以此類推。一個完成的int32型就出現了。但是由於java的原因,再做位移操作之前還是不能少了有符號轉無符號操作。
至此,我想讀者朋友,你應該完全理解了。
