1.字節序定義:是指整數在內存中保存的順序。
2.字節序種類:
a.Little endinan 低位存儲在內存的低地址,高位存儲在內存的高地址;
b.Big endian 高位存儲在內存的低地址,低位存儲在內存的高地址;
3.例子:
DWORD dwCount = 0x01020304;這樣的一個雙字節變量在內存中如下分布0013FF70 04 03 02 01
(注:實驗結果取之 XPSP3 VC6.0,說明我的機器是Little endinan序)
而如果是Big endian序的話,應該是0013FF70 01 02 03 04。用的比較多的x86系列的CPU,都是Little endinan序的。
而網絡字節序這是TCP/IP協議中定義好的一種數據表示格式,它是與你的機器的cpu,操作系統什么的無關的,這樣可以保證數據在網絡中傳輸時,不管怎么樣都能正確的解釋了,網
絡字節序選擇了Big endian。這樣就給編寫網絡程序的程序員帶來一個問題,程序員必須把本地數據從主機字節序轉換成網絡字節序發送到主機,同時,主機也必須把收到的數據從網
絡字節序轉換成本地字節序,這樣才能保證雙方正確的收發數據,不然就是產生bug。
4.winapi提供了四個函數用於進行網絡字節序到本機字節序和本機字節序到網絡字節序的轉換:
htons:把unsigned short類型從主機序轉換到網絡序
htonl:把unsigned long類型從主機序轉換到網絡序
ntohs:把unsigned short類型從網絡序轉換到主機序
ntohl:把unsigned long類型從網絡序轉換到主機序
(這四個API可以這樣記,s表示short,l表示long,n表示network,h表示host)
另外:char類型是沒有字節序的問題的,只有大於一個字節的數據類型才有字節序的問題。很多翻譯書籍將Little endinan翻譯成小端模式,將Big endian翻譯成大端模式。
5.用代碼判斷是否是大小端:
a.
1 bool IsLittleEndinan1() 2 { 3 int i = 1; 4 char *p = (char *)&i; 5 return *p == 1; 6 }
大小端存儲問題,如果小端方式中(i占至少兩個字節的長度)則i所分配的內存最小地址那個字節中就存着1,其他字節是0。大端的話則1在i的最高地址字節處存放,char是一個字
節,所以強制將char型量p指向i則p指向的一定是i的最低地址,那么就可以判斷p中的值是不是1來確定是不是小端。
b.
1 bool IsLittleEndinan2() 2 { 3 union u 4 { 5 int a; 6 char b; 7 }c; 8 c.a = 1; 9 10 return c.b == 1; 11 }
內存地址 | 0x4000 | 0x4001 |
存放內容 | 0x34 | 0x12 |
內存地址 | 0x4000 | 0x4001 |
存放內容 | 0x12 | 0x34 |
內存地址 | 0x4000 | 0x4001 | 0x4002 | 0x4003 |
存放內容 | 0x78 | 0x56 | 0x34 | 0x12 |
內存地址 | 0x4000 | 0x4001 | 0x4002 | 0x4003 |
存放內容 | 0x12 | 0x34 | 0x56 | 0x78 |
所謂的小端模式,是指數據的低位保存在內存的低地址中,而數 據的高位保存在內存的高地址中,這種存儲模式將地址的高低和數據位權有效地結合起來,高地址部分權值高,低地址部分權值低,和我們的邏輯方法一致。
為什么會有大小端模式之分呢?這是因為在計算機系統中,我們是以字節為單位的,每個地址單元都對應着一個字節,一個字節為 8bit。但是在C語言中除了8bit的char之外,還有16bit的short型,32bit的long型(要看具體的編譯器),另外,對於位數大於 8位的處理器,例如16位或者32位的處理器,由於寄存器寬度大於一個字節,那么必然存在着一個如果將多個字節安排的問題。因此就導致了大端存儲模式和小 端存儲模式。例如一個16bit的short型x,在內存中的地址為0x0010,x的值為0x1122,那么0x11為高字節,0x22為低字節。對於 大端模式,就將0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,剛好相反。我們常用的X86結構是小端模 式,而KEIL C51則為大端模式。很多的ARM,DSP都為小端模式。有些ARM處理器還可以由硬件來選擇是大端模式還是小端模式。
char x0,x1;
x=0x1122;
x0=((char*)&x)[0]; //低地址單元
x1=((char*)&x)[1]; //高地址單元
若x0=0x11,則是大端; 若x0=0x22,則是小端......
上面的程序還可以看出,數據尋址時,用的是低位字節的地址。