Big Endian 和 Little Endian
Peter Lee 2008-04-20
一、字節序
來(lái)自:
http://ayazh.gjjblog.com/archives/1058846/談到字節序的問(wèn)題,必然牽涉到兩大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存儲數據,而x86系列則采用little endian方式存儲數據。那么究竟什么是big endian,什么又是little endian呢?
其實(shí)big endian是指低地址存放最高有效字節(MSB),而little endian則是低地址存放最低有效字節(LSB)。
用文字說(shuō)明可能比較抽象,下面用圖像加以說(shuō)明。比如數字0x12345678在兩種不同字節序CPU中的存儲順序如下所示:
Big Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 78 | 56 | 34 | 12 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
從上面兩圖可以看出,采用big endian方式存儲數據是符合我們人類(lèi)的思維習慣的。而little endian,!@#$%^&*,見(jiàn)鬼去吧 -_-|||
為什么要注意字節序的問(wèn)題呢?你可能這么問(wèn)。當然,如果你寫(xiě)的程序只在單機環(huán)境下面運行,并且不和別人的程序打交道,那么你完全可以忽略字節序的存在。但是,如果你的程序要跟別人的程序產(chǎn)生交互呢?在這里我想說(shuō)說(shuō)兩種語(yǔ)言。C/C++語(yǔ)言編寫(xiě)的程序里數據存儲順序是跟編譯平臺所在的CPU相關(guān)的,而JAVA編寫(xiě)的程序則唯一采用big endian方式來(lái)存儲數據。試想,如果你用C/C++語(yǔ)言在x86平臺下編寫(xiě)的程序跟別人的JAVA程序互通時(shí)會(huì )產(chǎn)生什么結果?就拿上面的0x12345678來(lái)說(shuō),你的程序傳遞給別人的一個(gè)數據,將指向0x12345678的指針傳給了JAVA程序,由于JAVA采取big endian方式存儲數據,很自然的它會(huì )將你的數據翻譯為0x78563412。什么?竟然變成另外一個(gè)數字了?是的,就是這種后果。因此,在你的C程序傳給JAVA程序之前有必要進(jìn)行字節序的轉換工作。
無(wú)獨有偶,所有網(wǎng)絡(luò )協(xié)議也都是采用big endian的方式來(lái)傳輸數據的。所以有時(shí)我們也會(huì )把big endian方式稱(chēng)之為網(wǎng)絡(luò )字節序。當兩臺采用不同字節序的主機通信時(shí),在發(fā)送數據之前都必須經(jīng)過(guò)字節序的轉換成為網(wǎng)絡(luò )字節序后再進(jìn)行傳輸。ANSI C中提供了下面四個(gè)轉換字節序的宏。
big endian:最高字節在地址最低位,最低字節在地址最高位,依次排列。
little endian:最低字節在最低位,最高字節在最高位,反序排列。
endian指的是當物理上的最小單元比邏輯上的最小單元小時(shí),邏輯到物理的單元排布關(guān)系。咱們接觸到的物理單元最小都是byte,在通信領(lǐng)域中,這里往往是bit,不過(guò)原理也是類(lèi)似的。
一個(gè)例子:
如果我們將0x1234abcd寫(xiě)入到以0x0000開(kāi)始的內存中,則結果為
big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x34 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
目前應該little endian是主流,因為在數據類(lèi)型轉換的時(shí)候(尤其是指針轉換)不用考慮地址問(wèn)題。
二、Big Endian 和 Little Endian名詞的由來(lái)
這兩個(gè)術(shù)語(yǔ)來(lái)自于 Jonathan Swift 的《《格利佛游記》其中交戰的兩個(gè)派別無(wú)法就應該從哪一端--小端還是大端--打開(kāi)一個(gè)半熟的雞蛋達成一致。:)
“endian”這個(gè)詞出自《格列佛游記》。小人國的內戰就源于吃雞蛋時(shí)是究竟從大頭(Big-Endian)敲開(kāi)還是從小頭(Little-Endian)敲開(kāi),由此曾發(fā)生過(guò)六次叛亂,其中一個(gè)皇帝送了命,另一個(gè)丟了王位。
我們一般將endian翻譯成“字節序”,將big endian和little endian稱(chēng)作“大尾”和“小尾”。
在那個(gè)時(shí)代,Swift是在諷刺英國和法國之間的持續沖突,Danny Cohen,一位網(wǎng)絡(luò )協(xié)議的早期開(kāi)創(chuàng )者,第一次使用這兩個(gè)術(shù)語(yǔ)來(lái)指代字節順序,后來(lái)這個(gè)術(shù)語(yǔ)被廣泛接納了
三、Big Endian 和 Little Endian優(yōu)劣
來(lái)自:Dr. William T. Verts, April 19, 1996
Big Endian
判別一個(gè)數的正負很容易,只要取offset0處的一個(gè)字節就能確認。
Little Endian
長(cháng)度為1,2,4字節的數,排列方式都是一樣的,數據類(lèi)型轉換非常方便。
四、一些常見(jiàn)文件的字節序
來(lái)自: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
五、比特序
來(lái)自:
http://ayazh.gjjblog.com/archives/1058846/我在8月9號的《Big Endian和Little Endian》一文中談了字節序的問(wèn)題?墒怯信笥讶匀粫(huì )問(wèn),CPU存儲一個(gè)字節的數據時(shí)其字節內的8個(gè)比特之間的順序是否也有big endian和little endian之分?或者說(shuō)是否有比特序的不同?
實(shí)際上,這個(gè)比特序是同樣存在的。下面以數字0xB4(10110100)用圖加以說(shuō)明。
Big Endian
msb lsb
---------------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
lsb msb
---------------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
實(shí)際上,由于CPU存儲數據操作的最小單位是一個(gè)字節,其內部的比特序是什么樣對我們的程序來(lái)說(shuō)是一個(gè)黑盒子。也就是說(shuō),你給我一個(gè)指向0xB4這個(gè)數的指針,對于big endian方式的CPU來(lái)說(shuō),它是從左往右依次讀取這個(gè)數的8個(gè)比特;而對于little endian方式的CPU來(lái)說(shuō),則正好相反,是從右往左依次讀取這個(gè)數的8個(gè)比特。而我們的程序通過(guò)這個(gè)指針訪(fǎng)問(wèn)后得到的數就是0xB4,字節內部的比特序對于程序來(lái)說(shuō)是不可見(jiàn)的,其實(shí)這點(diǎn)對于單機上的字節序來(lái)說(shuō)也是一樣的。
那可能有人又會(huì )問(wèn),如果是網(wǎng)絡(luò )傳輸呢?會(huì )不會(huì )出問(wèn)題?是不是也要通過(guò)什么函數轉換一下比特序?嗯,這個(gè)問(wèn)題提得很好。假設little endian方式的CPU要傳給big endian方式CPU一個(gè)字節的話(huà),其本身在傳輸之前會(huì )在本地就讀出這個(gè)8比特的數,然后再按照網(wǎng)絡(luò )字節序的順序來(lái)傳輸這8個(gè)比特,這樣的話(huà)到了接收端不會(huì )出現任何問(wèn)題。而假如要傳輸一個(gè)32比特的數的話(huà),由于這個(gè)數在littel endian方存儲時(shí)占了4個(gè)字節,而網(wǎng)絡(luò )傳輸是以字節為單位進(jìn)行的,little endian方的CPU讀出第一個(gè)字節后發(fā)送,實(shí)際上這個(gè)字節是原數的LSB,到了接收方反倒成了MSB從而發(fā)生混亂。