補: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的記...