大端模式小端模式 主机序网络序
1.?主機序
不同的CPU有不同的字節序類型這些字節序是指整數在內存中保存的順序,這個叫做主機序。最常見的有兩種:
1.?????????Little endian:將低序字節存儲在起始地址。?即小端模式
2.?????????Big endian:將高序字節存儲在起始地址。????即大端模式
LE little-endian
最符合人的思維的字節序。地址低位存儲值的低位,地址高位存儲值的高位。怎么講是最符合人的思維的字節序,是因為從人的第一觀感來說低位值小,就應該放在內存地址小的地方,也即內存地址低位;反之,高位值就應該放在內存地址大的地方,也即內存地址高位。
BE big-endian
最直觀的字節序。地址低位存儲值的高位,地址高位存儲值的低位。為什么說直觀,不要考慮對應關系。只需要把內存地址從左到右按照由低到高的順序寫出,把值按照通常的高位到低位的順序寫出,兩者對照,一個字節一個字節的填充進去。
例子:在內存中雙字0x01020304(DWORD)的存儲方式:
內存地址
4000 4001 4002 4003
LE ??04 ??03 ??02 ??01
BE ??01 ??02 ??03 ??04
?
例子:1.如果我們將0x1234abcd寫入到以0x0000開始的內存中,則結果為:
big-endian??little-endian
0x0000??0x12?????0xcd
0x0001??0x23??????0xab
0x0002??0xab????? 0x34
0x0003??0xcd??????0x12
x86系列CPU都是little-endian的字節序。
二、網絡序
網絡字節順序是TCP/IP中規定好的一種數據表示格式,它與具體的CPU類型、操作系統等無關,從而可以保證數據在不同主機之間傳輸時能夠被正確解釋。網絡字節順序采用big endian排序方式。
為了進行轉換?bsd socket提供了轉換的函數有下面四個:
1.?????htons?把unsigned short類型從主機序轉換到網絡序。
2.?????htonl?把unsigned long類型從主機序轉換到網絡序。
3.?????ntohs?把unsigned short類型從網絡序轉換到主機序。
4.?????ntohl?把unsigned long類型從網絡序轉換到主機序。
在使用little endian的系統中這些函數會把字節序進行轉換,在使用big endian類型的系統中這些函數會定義成空宏。同樣在網絡程序開發時或是跨平臺開發時,也應該注意保證只用一種字節序,不然兩方的解釋不一樣就會產生bug。
注:
1.?????網絡與主機字節轉換函數:htons ntohs htonl ntohl?(s就是short,l是long,h是host,n是network)
2.?????不同的CPU上運行不同的操作系統,字節序也是不同的,參見下表
處理器????操作系統????字節排序
Alpha????全部????Little endian
HP-PA????NT????Little endian
HP-PA????UNIX????Big endian
Intelx86????全部????Little endian <-----x86系統是小端字節序系統
Motorola680x()????全部????Big endian
MIPS????NT????Little endian
MIPS????UNIX????Big endian
PowerPC????NT????Little endian
PowerPC????非NT????Big endian??<-----PPC系統是大端字節序系統
RS/6000????UNIX????Big endian
SPARC????UNIX????Big endian
IXP1200 ARM核心????全部????Little endian
三、一些注意點
1.BIG-ENDIAN、LITTLE-ENDIAN跟多字節類型的數據有關的比如int,short,long型,而對單字節數據byte卻沒有影響。BIG-ENDIAN就是低位字節排放在內存的高端,高位字節排放在內存的低端。而LITTLE-ENDIAN正好相反。
比如 int a = 0x05060708
在BIG-ENDIAN的情況下存放為:
字節號 0 1 2 3
數據 05 06 07 08
在LITTLE-ENDIAN的情況下存放為:
字節號 0 1 2 3
數據 08 07 06 05
2.BIG-ENDIAN、LITTLE-ENDIAN、跟CPU有關的,每一種CPU不是BIG-ENDIAN就是LITTLE- ENDIAN、。IA架構的CPU中是Little-Endian,而PowerPC 、SPARC和Motorola處理器。這其實就是所謂的主機字節序。而網絡字節序是指數據在網絡上傳輸時是大頭還是小頭的,在Internet的網絡字節序是BIG-ENDIAN。所謂的JAVA字節序指的是在JAVA虛擬機中多字節類型數據的存放順序,JAVA字節序也是BIG-ENDIAN。
3.所以在用C/C++寫通信程序時,在發送數據前務必用htonl和htons去把整型和短整型的數據進行從主機字節序到網絡字節序的轉換,而接收數據后對于整型和短整型數據則必須調用ntohl和ntohs實現從網絡字節序到主機字節序的轉換。如果通信的一方是JAVA程序、一方是 C/C++程序時,則需要在C/C++一側使用以上幾個方法進行字節序的轉換,而JAVA一側,則不需要做任何處理,因為JAVA字節序與網絡字節序都是 BIG-ENDIAN,只要C/C++一側能正確進行轉換即可(發送前從主機序到網絡序,接收時反變換)。如果通信的雙方都是JAVA,則根本不用考慮字節序的問題了。
4.如果網絡上全部是PowerPC,SPARC和Motorola CPU的主機那么不會出現任何問題,但由于實際存在大量的IA架構的CPU,所以經常出現數據傳輸錯誤。
5.如果程序運行在X86架構的PC SERVER上,發送數據的一端用C實現的,接收一端是用JAVA實現的,而發送端在發送數據前未進行從主機字節序到網絡字節序的轉換,這樣接收端接收到的是LITTLE-ENDIAN的數據,數據解釋自然出錯。
四、引用他人的
http://blog.csdn.net/xuyanbo2008/article/details/7458007
一、大端模式&小端模式
所謂的“大端模式”,是指數據的低位(就是權值較小的后面那幾位)保存在內存的高地址中,而數據的高位,保存在內存的低地址中,這樣的存儲模式有點兒類似于把數據當作字符串順序處理:地址由小向大增加,而數據從高位往低位放;
所謂的“小端模式”,是指數據的低位保存在內存的低地址中,而數據的高位保存在內存的高地址中,這種存儲模式將地址的高低和數據位權有效地結合起來,高地址部分權值高,低地址部分權值低,和我們的邏輯方法一致。
如果將一個32位的整數0x12345678 存放到一個整型變量(int)中,這個整型變量采用大端或者小端模式在內存中的存儲由下表所示。為簡單起見,本文使用OP0表示一個32位數據的最高字節MSB(Most Significant Byte),使用OP3表示一個32位數據最低字節LSB(Least Significant Byte)。??
地址偏移??????? 大端模式?????? 小端模式?
0x00?????????? 12(OP0)????? 78(OP3)?
0x01?????????? 34(OP1)????? 56(OP2)?
0x02?????????? 56(OP2)????? 34(OP1)?
0x03?????????? 78(OP3)????? 12(OP0)
小端:較高的有效字節存放在較高的存儲器地址,較低的有效字節存放在較低的存儲器地址。
大端:較高的有效字節存放在較低的存儲器地址,較低的有效字節存放在較高的存儲器地址。
采用大小模式對數據進行存放的主要區別在于在存放的字節順序,大端方式將高位存放在低地址,小端方式將高位存放在高地址。采用大端方式進行數據存放符合人類的正常思維,而采用小端方式進行數據存放利于計算機處理。到目前為止,采用大端或者小端進行數據存放,其孰優孰劣也沒有定論。
下面這段代碼可以用來測試一下你的編譯器是大端模式還是小端模式:
short int x;
char x0,x1;
x=0x1122;
x0=((char*)&x)[0]; //低地址單元
x1=((char*)&x)[1]; //高地址單元
若x0=0x11,則是大端; 若x0=0x22,則是小端......
上面的程序還可以看出,數據尋址時,用的是低位字節的地址
二、主機序&網絡序
不同的 CPU 有不同的字節序類型這些字節序是指整數在內存中保存的順序這個叫做主機序,最常見的有兩種:?
1、Little endian :將低序字節存儲在起始地址?
2、Big endian :將高序字節存儲在起始地址
網絡字節順序是TCP/IP中規定好的一種數據表示格式,它與具體的CPU類型、操作系統等無關,從而可以保證數據在不同主機之間傳輸時能夠被正確解釋。網絡字節順序采用big endian排序方式。
為了進行轉換 bsd socket提供了轉換的函數 有下面四個:
htons 把unsigned short類型從主機序轉換到網絡序
htonl 把unsigned long類型從主機序轉換到網絡序
ntohs 把unsigned short類型從網絡序轉換到主機序
ntohl 把unsigned long類型從網絡序轉換到主機序
在使用little endian的系統中,這些函數會把字節序進行轉換?
在使用big endian類型的系統中,這些函數會定義成空宏
同樣,在網絡程序開發時,或是跨平臺開發時,也應該注意保證只用一種字節序,不然兩方的解釋不一樣就會產生BUG。
注:
1、網絡與主機字節轉換函數:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)
2、不同的CPU上運行不同的操作系統,字節序也是不同的,參見下表:
處理器???????????? 操作系統???? 字節排序
Alpha?????????????????? 全部????? Little endian
HP-PA??????????????????? NT?????? Little endian
HP-PA?????????????????? UNIX???? Big endian
Intelx86??????????????? 全部???? Little endian <-----x86系統是小端字節序系統
Motorola680x()????????? 全部??? Big endian
MIPS???????????????????? NT?????? Little endian
MIPS??????????????????? UNIX??? Big endian
PowerPC????????????????? NT???? Little endian
PowerPC???????????????? 非NT??? Big endian?? <-----PPC系統是大端字節序系統
RS/6000???????????????? UNIX??? Big endian
SPARC?????????????????? UNIX??? Big endian
IXP1200 ARM核心???????? 全部????? Little endian
下面是一個檢驗本機字節序的簡便方法:
//判斷本機的字節序
//返回true表為小段序。返回false表示為大段序
bool am_little_endian ()
{
unsigned short i=1;
return (int)*((char *)(&i)) ? true : false;
}
int main()
{
?? if(am_little_endian())
{
???????? ?? printf("本機字節序為小段序!\n");
}
else
{
????????? printf("本機字節序為大段序!\n");
}
??????? return 0;
}
三、入棧地址高低問題
堆棧是在內存中指定的一段特殊存儲區,存起始單元的地址叫棧底,當前存儲單元地址叫棧頂,堆棧存儲區一旦指定,棧底就固定不變了,而棧頂是隨入棧、出棧操作呈動態。而不同機型的堆棧設計,有兩種情況:一是每入棧一個數,棧頂地址加1,每出棧一個數,棧頂地址減1,即堆棧區是由內存的低地址向高地址。另一種是每入棧一個數,棧頂地址減1,每出棧一個數,棧頂地址加1,即堆棧區是由內存的高地址向低地址。高地址、低地址是相對而言,即相對地址編碼的大小而言。
總結
以上是生活随笔為你收集整理的大端模式小端模式 主机序网络序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Http协议】深入理解HTTP协议
- 下一篇: 网口扫盲一:网卡初步认识