轉(zhuǎn)發(fā)來自http://www.ruanyifeng.com/blog/2016/11/byte-order.html
計算機硬件有兩種儲存數(shù)據(jù)的方式:大端字節(jié)序(big endian)和小端字節(jié)序(little endian)。
舉例來說,數(shù)值0x2211使用兩個字節(jié)儲存:高位字節(jié)是0x22,低位字節(jié)是0x11。
- 大端字節(jié)序:高位字節(jié)在前,低位字節(jié)在后,這是人類讀寫數(shù)值的方法。
- 小端字節(jié)序:低位字節(jié)在前,高位字節(jié)在后,即以
0x1122形式儲存。

同理,0x1234567的大端字節(jié)序和小端字節(jié)序的寫法如下圖。

我一直不理解,為什么要有字節(jié)序,每次讀寫都要區(qū)分,多麻煩!統(tǒng)一使用大端字節(jié)序,不是更方便嗎?
上周,我讀到了一篇文章,解答了所有的疑問。而且,我發(fā)現(xiàn)原來的理解是錯的,字節(jié)序其實很簡單。
首先,為什么會有小端字節(jié)序?
答案是,計算機電路先處理低位字節(jié),效率比較高,因為計算都是從低位開始的。所以,計算機的內(nèi)部處理都是小端字節(jié)序。
但是,人類還是習慣讀寫大端字節(jié)序。所以,除了計算機的內(nèi)部處理,其他的場合幾乎都是大端字節(jié)序,比如網(wǎng)絡(luò)傳輸和文件儲存。
計算機處理字節(jié)序的時候,不知道什么是高位字節(jié),什么是低位字節(jié)。它只知道按順序讀取字節(jié),先讀第一個字節(jié),再讀第二個字節(jié)。
如果是大端字節(jié)序,先讀到的就是高位字節(jié),后讀到的就是低位字節(jié)。小端字節(jié)序正好相反。
理解這一點,才能理解計算機如何處理字節(jié)序。
字節(jié)序的處理,就是一句話:
"只有讀取的時候,才必須區(qū)分字節(jié)序,其他情況都不用考慮。"
處理器讀取外部數(shù)據(jù)的時候,必須知道數(shù)據(jù)的字節(jié)序,將其轉(zhuǎn)成正確的值。然后,就正常使用這個值,完全不用再考慮字節(jié)序。
即使是向外部設(shè)備寫入數(shù)據(jù),也不用考慮字節(jié)序,正常寫入一個值即可。外部設(shè)備會自己處理字節(jié)序的問題。
舉例來說,處理器讀入一個16位整數(shù)。如果是大端字節(jié)序,就按下面的方式轉(zhuǎn)成值。
x = buf[offset] * 256 + buf[offset+1];
上面代碼中,buf是整個數(shù)據(jù)塊在內(nèi)存中的起始地址,offset是當前正在讀取的位置。第一個字節(jié)乘以256,再加上第二個字節(jié),就是大端字節(jié)序的值,這個式子可以用邏輯運算符改寫。
x = buf[offset]<<8 | buf[offset+1];
上面代碼中,第一個字節(jié)左移8位(即后面添8個0),然后再與第二個字節(jié)進行或運算。
如果是小端字節(jié)序,用下面的公式轉(zhuǎn)成值。
x = buf[offset+1] * 256 + buf[offset];
32位整數(shù)的求值公式也是一樣的。
/* 大端字節(jié)序 */ i = (data[3]<<0) | (data[2]<<8) | (data[1]<<16) | (data[0]<<24); /* 小端字節(jié)序 */ i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);