1、字節序java
來自:http://ayazh.gjjblog.com/archives/1058846/swift
談到字節序的問題,必然牽涉到兩大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列採用big endian方式存儲數據,而x86系列則採用little endian方式存儲數據。那麼究竟什麼是big endian,什麼又是little endian呢?
其實big endian是指低地址存放最高有效字節(MSB),而little endian則是低地址存放最低有效字節(LSB)。網絡
用文字說明可能比較抽象,下面用圖像加以說明。好比數字0x12345678在兩種不一樣字節序CPU中的存儲順序以下所示:
Big Endianide
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian函數
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 78 | 56 | 34 | 12 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
從上面兩圖能夠看出,採用big endian方式存儲數據是符合咱們人類的思惟習慣的。而little endian,!@#$%^&*,見鬼去吧 -_-|||
爲何要注意字節序的問題呢?你可能這麼問。固然,若是你寫的程序只在單機環境下面運行,而且不和別人的程序打交道,那麼你徹底能夠忽略字節序的存在。可是,若是你的程序要跟別人的程序產生交互呢?在這裏我想說說兩種語言。C/C++語言編寫的程序裏數據存儲順序是跟編譯平臺所在的CPU相關的,而Java編寫的程序則惟一採用big endian方式來存儲數據。試想,若是你用C/C++語言在x86平臺下編寫的程序跟別人的JAVA程序互通時會產生什麼結果?就拿上面的0x12345678來講,你的程序傳遞給別人的一個數據,將指向0x12345678的指針傳給了JAVA程序,因爲JAVA採起big endian方式存儲數據,很天然的它會將你的數據翻譯爲0x78563412。什麼?居然變成另一個數字了?是的,就是這種後果。所以,在你的C程序傳給JAVA程序以前有必要進行字節序的轉換工做。
無獨有偶,全部網絡協議也都是採用big endian的方式來傳輸數據的。因此有時咱們也會把big endian方式稱之爲網絡字節序。當兩臺採用不一樣字節序的主機通訊時,在發送數據以前都必須通過字節序的轉換成爲網絡字節序後再進行傳輸。ANSI C中提供了下面四個轉換字節序的宏。ui
big endian:最高字節在地址最低位,最低字節在地址最高位,依次排列。
little endian:最低字節在最低位,最高字節在最高位,反序排列。.net
endian指的是當物理上的最小單元比邏輯上的最小單元小時,邏輯到物理的單元排布關係。我們接觸到的物理單元最小都是byte,在通訊領域中,這裏每每是bit,不過原理也是相似的。翻譯
一個例子:
若是咱們將0x1234abcd寫入到以0x0000開始的內存中,則結果爲
big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x34 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
目前應該little endian是主流,由於在數據類型轉換的時候(尤爲是指針轉換)不用考慮地址問題。指針
2、Big Endian 和 Little Endian名詞的由來code
這兩個術語來自於 Jonathan Swift 的《《格利佛遊記》其中交戰的兩個派別沒法就應該從哪一端--小端仍是大端--打開一個半熟的雞蛋達成一致。:)
「endian」這個詞出自《格列佛遊記》。小人國的內戰就源於吃雞蛋時是究竟從大頭(Big-Endian)敲開仍是從小頭(Little-Endian)敲開,由此曾發生過六次叛亂,其中一個皇帝送了命,另外一個丟了王位。
咱們通常將endian翻譯成「字節序」,將big endian和little endian稱做「大尾」和「小尾」。
在那個時代,Swift是在諷刺英國和法國之間的持續衝突,Danny Cohen,一位網絡協議的早期開創者,第一次使用這兩個術語來指代字節順序,後來這個術語被普遍接納了
3、Big Endian 和 Little Endian優劣
來自:Dr. William T. Verts, April 19, 1996
Big Endian
判別一個數的正負很容易,只要取offset0處的一個字節就能確認。
Little Endian
長度爲1,2,4字節的數,排列方式都是同樣的,數據類型轉換很是方便。
4、一些常見文件的字節序
來自:Dr. William T. Verts, April 19, 1996
Common file formats and their endian order are as follows:
5、比特序
來自:http://ayazh.gjjblog.com/archives/1058846/
我在8月9號的《Big Endian和Little Endian》一文中談了字節序的問題。但是有朋友仍然會問,CPU存儲一個字節的數據時其字節內的8個比特之間的順序是否也有big endian和little endian之分?或者說是否有比特序的不一樣?
實際上,這個比特序是一樣存在的。下面以數字0xB4(10110100)用圖加以說明。
Big Endian
msb lsb
---------------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
lsb msb ----------------------------------------------> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 實際上,因爲CPU存儲數據操做的最小單位是一個字節,其內部的比特序是什麼樣對咱們的程序來講是一個黑盒子。也就是說,你給我一個指向0xB4這個數的指針,對於big endian方式的CPU來講,它是從左往右依次讀取這個數的8個比特;而對於little endian方式的CPU來講,則正好相反,是從右往左依次讀取這個數的8個比特。而咱們的程序經過這個指針訪問後獲得的數就是0xB4,字節內部的比特序對於程序來講是不可見的,其實這點對於單機上的字節序來講也是同樣的。 那可能有人又會問,若是是網絡傳輸呢?會不會出問題?是否是也要經過什麼函數轉換一下比特序?嗯,這個問題提得很好。假設little endian方式的CPU要傳給big endian方式CPU一個字節的話,其自己在傳輸以前會在本地就讀出這個8比特的數,而後再按照網絡字節序的順序來傳輸這8個比特,這樣的話到了接收端不會出現任何問題。而假如要傳輸一個32比特的數的話,因爲這個數在littel endian方存儲時佔了4個字節,而網絡傳輸是以字節爲單位進行的,little endian方的CPU讀出第一個字節後發送,實際上這個字節是原數的LSB,到了接收方反倒成了MSB從而發生混亂。