大端跟小端

2021-06-05 14:30:38 字數 2527 閱讀 7198

補:x86機是小端(修改分割槽表時要注意),微控制器一般為大端

今天碰乙個關於位元組順序的問題,雖然看起來很簡單,但一直都沒怎麼完全明白這個東西,索性就找了下資料,把它弄清楚.

因為現行的計算機都是以八位乙個位元組為儲存單位,那麼乙個16位的整數,也就是c語言中的short,在記憶體中可能有兩種儲存順序big-endian和 litte-endian.考慮乙個short整數0x3132(0x32是低位,0x31是高位),把它賦值給乙個short變數,那麼它在記憶體中的存 儲可能有如下兩種情況:

大端位元組(big-endian):

----------------->>>>>>>>記憶體位址增大方向

short變數位址

0x1000                         0x1001

_____________________________

|                                    |

| 0x31                         | 0x32

|_______________ | ________________

高位位元組在低位位元組的前面,也就是高位在記憶體位址低的一端.可以這樣記住(大端->高位->在前->正常的邏輯順序)

小端位元組(little-endian):

----------------->>>>>>>>記憶體位址增大方向

short變數位址

0x1000                          0x1001

_____________________________

|                                      |

| 0x32                            | 0x31

|________________ | ________________

低位位元組在高位位元組的前面,也就是低位在記憶體位址低的一端.可以這樣記住(小端->低位->在前->與正常邏輯順序相反)

可以做個實驗

在windows上下如下程式

#include

#include

void main( void )

然後在c盤下開啟test.txt檔案,可以看見內容是21,而test等於0x3132,可以明顯的看出來x86的位元組順序是低位在前.如果我們把這段 同樣的**放到(big-endian)的機器上執行,那麼打出來的檔案就是12.這在本機中使用是沒有問題的.但當你把這個檔案從乙個big- endian機器複製到乙個little-endian機器上時就出現問題了.

如上述例子,我們在big-endian的機器上建立了這個test檔案,把其複製到little-endian的機器上再用fread讀到乙個 short裡面,我們得到的就不再是0x3132而是0x3231了,這樣讀到的資料就是錯誤的,所以在兩個位元組順序不一樣的機器上傳輸資料時需要特別小 心位元組順序,理解了位元組順序在可以幫助我們寫出移植行更高的**.

正因為有位元組順序的差別,所以在網路傳輸的時候定義了所有位元組順序相關的資料都使用big-endian,bsd的**中定義了四個巨集來處理:

#define ntohs(n) //網路位元組順序到主機位元組順序 n代表net, h代表host, s代表short

#define htons(n) //主機位元組順序到網路位元組順序 n代表net, h代表host, s代表short

#define ntohl(n) //網路位元組順序到主機位元組順序 n代表net, h代表host, s代表 long

#define htonl(n) //主機位元組順序到網路位元組順序 n代表net, h代表host, s代表 long

舉例說明下這其中乙個巨集的實現:

#define sw16(x) \

((short)( \

(((short)(x) & (short)0x00ffu) << 8) | \

(((short)(x) & (short)0xff00u) >> 8) ))

這裡實現的是乙個交換兩個位元組順序.其他幾個巨集類似.

我們改寫一下上面的程式

#include

#include

#define sw16(x) \

((short)( \

(((short)(x) & (short)0x00ffu) << 8) | \

(((short)(x) & (short)0xff00u) >> 8) ))

// 因為x86下面是低位在前,需要交換一下變成網路位元組順序

#define htons(x) sw16(x)

void main( void )

如果在高位元組在前的機器上,由於與網路位元組順序一致,所以我們什麼都不幹就可以了,只需要把#define htons(x) sw16(x)巨集替換為 #define htons(x) (x).

一開始我在理解這個問題時,總在想為什麼其他資料不用交換位元組順序?比如說我們write一塊buffer到檔案,最後終於想明白了,因為都是unsigned char型別乙個位元組乙個位元組的寫進去,這個順序是固定的,不存在位元組順序的問題,夠笨啊..

大端與小端

網際網路使用網路位元組順序採用大端模式進行編址,大端儲存也稱為網路位元組序,因為tcp ip包在網路中傳輸時都要求以這種次序,以其他形式儲存資料的機器 主機位元組順序根據處理器的不同而不同,如powerpc處理器,使用大端模式,而pentuim處理器使用小端模式 則必須在傳送資料之前把首部轉換成網路...

大端與小端

端模式 endian 的這個詞出自 jonathan swift 書寫的 格列佛遊記 這本書根據將雞蛋敲開的方法不同將所有的人分為兩類,從圓頭開始將雞蛋敲開的人被歸為 big endian 從尖頭開始將雞蛋敲開的人被歸為 littile endian 小人國的內戰就源於吃雞蛋時是究竟從大頭 big ...

大端與小端

大端表示跟小端表示這兩者的具體意義我老是記不住,當然不是說它的意思不懂,而只是容易搞混。現在記一下,以後就比較有印象了。在c 中,定義乙個int值的時候,它所占用的記憶體是4個位元組,然而這4個位元組裡面,我們如果得到這個int值的記憶體位址,其實就是它的最低位置的位址,如 int a 假設 a的記...