一、字節序
來自: http://ayazh.gjjblog.com/archives/1058846/
談到字節序的問題,必然牽涉到兩大
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 Endian
低地址
高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 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
中提供了下面四個轉換字節序的宏。
big endian
:最高字節在地址最低位,最低字節在地址最高位,依次排列。
little endian
:最低字節在最低位,最高字節在最高位,反序排列。
endian 指的是當物理上的最小單元比邏輯上的最小單元小時,邏輯到物理的單元排布關係。咱們接觸到的物理單元最小都是byte ,在通信領域中,這裏往往是bit ,不過原理也是類似的。
一個例子:
如果我們將0x1234abcd
寫入到以0x0000
開始的內存中,則結果爲
big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x34 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
目前應該little endian
是主流,因爲在數據類型轉換的時候(尤其是指針轉換)不用考慮地址問題。
二、 Big Endian 和 Little Endian 名詞的由來
這兩個術語來自於 Jonathan Swift 的《《格利佛遊記》其中交戰的兩個派別無法就應該從哪一端--小端還是大端--打開一個半熟的雞蛋達成一致。:)
“ endian ”這個詞出自《格列佛遊記》。小人國的內戰就源於吃雞蛋時是究竟從大頭 (Big-Endian) 敲開還是從小頭 (Little-Endian) 敲開,由此曾發生過六次叛亂,其中一個皇帝送了命,另一個丟了王位。
我們一般將 endian 翻譯成“字節序”,將 big endian 和 little endian 稱作“大尾”和“小尾”。
在那個時代,
Swift
是在諷刺英國和法國之間的持續衝突,
Danny Cohen
,一位網絡協議的早期開創者,第一次使用這兩個術語來指代字節順序,後來這個術語被廣泛接納了
三、 Big Endian 和 Little Endian 優劣
來自: Dr. William T. Verts, April 19, 1996
Big Endian
判別一個數的正負很容易,只要取 offset0 處的一個字節就能確認。
Little Endian
長度爲 1 , 2 , 4 字節的數,排列方式都是一樣的,數據類型轉換非常方便。
四、一些常見文件的字節序
來自: Dr. William T. Verts, April 19, 1996
Common file formats and their endian order are as follows:
- Adobe Photoshop -- Big Endian
- BMP (Windows and OS/2 Bitmaps) -- Little Endian
- DXF (AutoCad) -- Variable
- GIF -- Little Endian
- IMG (GEM Raster) -- Big Endian
- JPEG -- Big Endian
- FLI (Autodesk Animator) -- Little Endian
- MacPaint -- Big Endian
- PCX (PC Paintbrush) -- Little Endian
- PostScript -- Not Applicable (text!)
- POV (Persistence of Vision ray-tracer) -- Not Applicable (text!)
- QTM (Quicktime Movies) -- Little Endian (on a Mac!) (PeterLee 注Big Endian in my opinion )
- Microsoft RIFF (.WAV & .AVI) -- Both
- Microsoft RTF (Rich Text Format) -- Little Endian
- SGI (Silicon Graphics) -- Big Endian
- Sun Raster -- Big Endian
- TGA (Targa) -- Little Endian
- TIFF -- Both, Endian identifier encoded into file
- WPG (WordPerfect Graphics Metafile) -- Big Endian (on a PC!)
- XWD (X Window Dump) -- Both, Endian identifier encoded into file
五、比特序
來自: 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
從而發生混亂。
轉自:http://blog.csdn.net/sunshine314/2008/4/20/2309655.aspx