網絡字節序和本機字節序


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 }
剖析:
嵌入式系統開發者應該對Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU對操作數的存放方式是從低字節到高字節,而Big-endian模式對操作數的存放方
式是從高字節到低字節。例如,16bit寬的數0x1234在Little-endian模式CPU內存中的存放方式(假設從地址0x4000開始存放)為:
內存地址 0x4000 0x4001
存放內容 0x34 0x12
而在 Big-endian 模式 CPU 內存中的存放方式則為:
內存地址 0x4000 0x4001
存放內容 0x12 0x34
32bit 寬的數 0x12345678 Little-endian 模式 CPU 內存中的存放方式(假設從地址 0x4000 開始存放)為:
內存地址 0x4000 0x4001 0x4002 0x4003
存放內容 0x78 0x56 0x34 0x12
而在 Big-endian 模式 CPU 內存中的存放方式則為:
內存地址 0x4000 0x4001 0x4002 0x4003
存放內容 0x12 0x34 0x56 0x78
聯合體 union 的存放順序是所有成員都從低地址開始存放,面試者的解答利用該特性,輕松地獲得了 CPU 對內存采用 Little-endian 還是 Big-endian 模式讀寫。如果誰能當場給出這個解答,那簡直就是一個天才的程序員。
 
 
補充:
所謂的大端模式,是指數據的低位(就是權值較小的后面那幾位)保存在內存的高地址中,而數據的高位,保存在內存的低地址中,這樣的存儲模式有點兒類似於把數據當作字符串順序處理:地址由小向大增加,而數據從高位往低位放;
   所謂的小端模式,是指數據的低位保存在內存的低地址中,而數 據的高位保存在內存的高地址中,這種存儲模式將地址的高低和數據位權有效地結合起來,高地址部分權值高,低地址部分權值低,和我們的邏輯方法一致。
   為什么會有大小端模式之分呢?這是因為在計算機系統中,我們是以字節為單位的,每個地址單元都對應着一個字節,一個字節為 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處理器還可以由硬件來選擇是大端模式還是小端模式。
 
   下面這段代碼可以用來測試一下你的編譯器是大端模式還是小端模式:
 
short int x;
char x0,x1;
x=0x1122;
x0=((char*)&x)[0]; //低地址單元
x1=((char*)&x)[1]; //高地址單元
若x0=0x11,則是大端; 若x0=0x22,則是小端......
上面的程序還可以看出,數據尋址時,用的是低位字節的地址。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM