標籤:style c blog java http a
1.有效位
在談位元組序前需要先瞭解有效位,有效位分為兩種:最低有效位(LSB: Least Significant Bit) 和最高有效位(MSB:Most Significant Bit)。在位元中,LSB是最低加權位,與十進位數字中最右邊的一位類似;MSB是最高加權位,與十進位數字中最左邊的一位類似。通常,MSB位於位元的最左側,LSB位於位元的最右側。以一個十進位的數12345678為例,最高有效位就是1,最低有效位就是8。
2.位元組序:
位元組序,顧名思義位元組的順序,就是大於一個位元組類型的資料在記憶體中的存放順序(一個位元組的資料當然就無需談順序的問題了)。位元組序分為兩類:Big-Endian和Little-Endian,具體定義入下:
a) Little-Endian就是低位位元組排放在記憶體的低地址端,高位位元組排放在記憶體的高地址端。
b) Big-Endian就是高位位元組排放在記憶體的低地址端,低位位元組排放在記憶體的高地址端。
用文字說明可能比較抽象,下面用映像加以說明。比如數字0x12345678在兩種不同位元組序CPU中的儲存順序如下所示:
從上面兩圖可以看出,採用big endian方式儲存資料是符合我們人類的思維習慣的。
為什麼要注意位元組序的問題呢?你可能這麼問。當然,如果你寫的程式只在單機環境下面運行,並且不和別人的程式打交道,那麼你完全可以忽略位元組序的存在。但是,如果你的程式要跟別人的程式產生互動呢?在這裡我想說說兩種語言。C/C++語言編寫的程式裡資料存放區順序是跟編譯平台所在的CPU相關的,而JAVA編寫的程式則唯一採用big endian方式來儲存資料。試想,如果你用C/C++語言在x86平台下編寫的程式跟別人的JAVA程式互連時會產生什麼結果?就拿上面的0x12345678來說,你的程式傳遞給別人的一個資料,將指向0x12345678的指標傳給了JAVA程式,由於JAVA採取big endian方式儲存資料,很自然的它會將你的資料翻譯為0x78563412。什嗎?竟然變成另外一個數字了?是的,就是這種後果。因此,在你的C程式傳給JAVA程式之前有必要進行位元組序的轉換工作。
3.Big-Endian和Little-Endian優缺點
Big-Endian優點:判別一個數的正負很容易,只要取offset0處的一個位元組就能確認。你不必知道這個數值有多長,或者你也不必過一些位元組來看這個數值是否含有符號位。這個數值是以它們被列印出來的順序存放的,所以從二進位到十進位的函數特別有效。
Little-Endian優點:長度為1,2,4位元組的數,相片順序都是一樣的,資料類型轉換非常方便。提取一個,兩個,四個或者更長位元組資料的彙編指令以與其他所有格式相同的方式進行:首先在位移地址為0的地方提取最低位的位元組,因為地址位移和位元組數是一對一的關係,多重精度的數學函數就相對地容易寫了。
如果你增加數位值,你可能在左邊增加數字(高位非指數函數需要更多的數字)。因此,經常需要增加兩位元字並移動儲存空間裡所有Big-endian順序的數字,把所有數向右移,這會增加電腦的工作量。不過,使用Little- Endian的儲存空間中不重要的位元組可以存在它原來的位置,新的數可以存在它的右邊的高位地址裡。這就意味著電腦中的某些計算可以變得更加簡單和快速。
4.JAVA位元組序
BIG-ENDIAN、LITTLE-ENDIAN跟多位元組類型的資料有關,比如int,short,long型,而對單位元組資料byte卻沒有影響。BIG-ENDIAN就是低位位元組排放在記憶體的高端,高位位元組排放在記憶體的低端。而LITTLE-ENDIAN正好相反。
比如 int a = 0x05060708
在BIG-ENDIAN的情況下存放為:
位元組號 0 1 2 3
資料 05 06 07 08
在LITTLE-ENDIAN的情況下存放為:
位元組號 0 1 2 3
資料 08 07 06 05
5.網路位元組序:
無專屬偶,所有網路通訊協定也都是採用big endian的方式來傳輸資料的。所以有時我們也會把big endian方式稱之為網路位元組序。當兩台採用不同位元組序的主機通訊時,在發送資料之前都必須經過位元組序的轉換成為網路位元組序後再進行傳輸。
6.JAVA樣本:
我們首先看下java預設byteorder下的結果:
1: public static void byteOrderForIntTest(){
2: ByteBuffer buf =ByteBuffer.allocate(10);
3: System.out.println("Default java endian: "+buf.order().toString());
4:
5: buf.putInt(1);
6: buf.putInt(2);
7:
8: buf.flip();
9: for(int i=0;i<buf.limit();i++){
10: System.out.println(buf.get());
11: }
12: }
執行結果為:
然後我們再修改下byteOrder:
1: public static void byteOrderForIntTest(){
2: ByteBuffer buf =ByteBuffer.allocate(10);
3: System.out.println("Default java endian: "+buf.order().toString());
4:
5: buf.order(ByteOrder.LITTLE_ENDIAN);
6: System.out.println("now java endian: "+buf.order().toString());
7:
8: buf.putInt(1);
9: buf.putInt(2);
10:
11: buf.flip();
12: for(int i=0;i<buf.limit();i++){
13: System.out.println(buf.get());
14: }
15: }
執行結果為:
參考資料:
1.http://baike.baidu.com/link?url=awoDFcwi9mo7zg-Kfk6UhFousPHs4_-OhoivX-Hg74e_DSQqbn8glPIVTXIMsueLRYLgDYJXG1hXHekFnUdMPa2.http://baike.baidu.com/link?url=H235MhpFB3PN_DX_ke6CVKqKuXWDprMDLoT6iuwJYP10vMGJNYdgG_mn5lw1gc-bkaRRXXPnNn_toQl5oSTQKK3.http://blog.csdn.net/sunshine1314/article/details/2309655