Big Endian 和 Little Endian [轉]

Big Endian 和 Little Endian [轉]
powerpc 發表於 2005-5-5 15:25:00

談到字節序的問題,必然牽涉到兩大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中提供了下面四個轉換字節序的宏。
·BE和LE一文的補完

我在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從而發生混亂。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章