大端模式小端模式、主机序网络序、入栈地址高低问题
所謂的“大端模式”,是指數(shù)據(jù)的低位(就是權(quán)值較小的后面那幾位)保存在內(nèi)存的高地址中,而數(shù)據(jù)的高位,保存在內(nèi)存的低地址中,這樣的存儲(chǔ)模式有點(diǎn)兒類似于把數(shù)據(jù)當(dāng)作字符串順序處理:地址由小向大增加,而數(shù)據(jù)從高位往低位放;
所謂的“小端模式”,是指數(shù)據(jù)的低位保存在內(nèi)存的低地址中,而數(shù)據(jù)的高位保存在內(nèi)存的高地址中,這種存儲(chǔ)模式將地址的高低和數(shù)據(jù)位權(quán)有效地結(jié)合起來,高地址部分權(quán)值高,低地址部分權(quán)值低,和我們的邏輯方法一致。
如果將一個(gè)32位的整數(shù)0x12345678 存放到一個(gè)整型變量(int)中,這個(gè)整型變量采用大端或者小端模式在內(nèi)存中的存儲(chǔ)由下表所示。為簡單起見,本文使用OP0表示一個(gè)32位數(shù)據(jù)的最高字節(jié)MSB(Most Significant Byte),使用OP3表示一個(gè)32位數(shù)據(jù)最低字節(jié)LSB(Least Significant Byte)。??
地址偏移??????? 大端模式?????? 小端模式?
0x00?????????? 12(OP0)????? 78(OP3)?
0x01?????????? 34(OP1)????? 56(OP2)?
0x02?????????? 56(OP2)????? 34(OP1)?
0x03?????????? 78(OP3)????? 12(OP0)
小端:較高的有效字節(jié)存放在較高的存儲(chǔ)器地址,較低的有效字節(jié)存放在較低的存儲(chǔ)器地址。
大端:較高的有效字節(jié)存放在較低的存儲(chǔ)器地址,較低的有效字節(jié)存放在較高的存儲(chǔ)器地址。
采用大小模式對(duì)數(shù)據(jù)進(jìn)行存放的主要區(qū)別在于在存放的字節(jié)順序,大端方式將高位存放在低地址,小端方式將高位存放在高地址。采用大端方式進(jìn)行數(shù)據(jù)存放符合人類的正常思維,而采用小端方式進(jìn)行數(shù)據(jù)存放利于計(jì)算機(jī)處理。到目前為止,采用大端或者小端進(jìn)行數(shù)據(jù)存放,其孰優(yōu)孰劣也沒有定論。
下面這段代碼可以用來測試一下你的編譯器是大端模式還是小端模式:
short int x;
char x0,x1;
x=0x1122;
x0=((char*)&x)[0]; //低地址單元
x1=((char*)&x)[1]; //高地址單元
若x0=0x11,則是大端; 若x0=0x22,則是小端......
上面的程序還可以看出,數(shù)據(jù)尋址時(shí),用的是低位字節(jié)的地址
二、主機(jī)序&網(wǎng)絡(luò)序
不同的 CPU 有不同的字節(jié)序類型這些字節(jié)序是指整數(shù)在內(nèi)存中保存的順序這個(gè)叫做主機(jī)序,最常見的有兩種:?
1、Little endian :將低序字節(jié)存儲(chǔ)在起始地址?
2、Big endian :將高序字節(jié)存儲(chǔ)在起始地址
網(wǎng)絡(luò)字節(jié)順序是TCP/IP中規(guī)定好的一種數(shù)據(jù)表示格式,它與具體的CPU類型、操作系統(tǒng)等無關(guān),從而可以保證數(shù)據(jù)在不同主機(jī)之間傳輸時(shí)能夠被正確解釋。網(wǎng)絡(luò)字節(jié)順序采用big endian排序方式。
為了進(jìn)行轉(zhuǎn)換 bsd socket提供了轉(zhuǎn)換的函數(shù) 有下面四個(gè):
htons 把unsigned short類型從主機(jī)序轉(zhuǎn)換到網(wǎng)絡(luò)序
htonl 把unsigned long類型從主機(jī)序轉(zhuǎn)換到網(wǎng)絡(luò)序
ntohs 把unsigned short類型從網(wǎng)絡(luò)序轉(zhuǎn)換到主機(jī)序
ntohl 把unsigned long類型從網(wǎng)絡(luò)序轉(zhuǎn)換到主機(jī)序
在使用little endian的系統(tǒng)中,這些函數(shù)會(huì)把字節(jié)序進(jìn)行轉(zhuǎn)換?
在使用big endian類型的系統(tǒng)中,這些函數(shù)會(huì)定義成空宏
同樣,在網(wǎng)絡(luò)程序開發(fā)時(shí),或是跨平臺(tái)開發(fā)時(shí),也應(yīng)該注意保證只用一種字節(jié)序,不然兩方的解釋不一樣就會(huì)產(chǎn)生BUG。
注:
1、網(wǎng)絡(luò)與主機(jī)字節(jié)轉(zhuǎn)換函數(shù):htons ntohs htonl ntohl (s 就是short l是long h是host n是network)
2、不同的CPU上運(yùn)行不同的操作系統(tǒng),字節(jié)序也是不同的,參見下表:
處理器???????????? 操作系統(tǒng)???? 字節(jié)排序
Alpha?????????????????? 全部????? Little endian
HP-PA??????????????????? NT?????? Little endian
HP-PA?????????????????? UNIX???? Big endian
Intelx86??????????????? 全部???? Little endian <-----x86系統(tǒng)是小端字節(jié)序系統(tǒng)
Motorola680x()????????? 全部??? Big endian
MIPS???????????????????? NT?????? Little endian
MIPS??????????????????? UNIX??? Big endian
PowerPC????????????????? NT???? Little endian
PowerPC???????????????? 非NT??? Big endian?? <-----PPC系統(tǒng)是大端字節(jié)序系統(tǒng)
RS/6000???????????????? UNIX??? Big endian
SPARC?????????????????? UNIX??? Big endian
IXP1200 ARM核心???????? 全部????? Little endian
?
下面是一個(gè)檢驗(yàn)本機(jī)字節(jié)序的簡便方法:
//判斷本機(jī)的字節(jié)序
//返回true表為小段序。返回false表示為大段序
bool am_little_endian ()
{
unsigned short i=1;
return (int)*((char *)(&i)) ? true : false;
}
int main()
{
?? if(am_little_endian())
{
???????? ?? printf("本機(jī)字節(jié)序?yàn)樾《涡?\n");
}
else
{
????????? printf("本機(jī)字節(jié)序?yàn)榇蠖涡?\n");
}
??????? return 0;
}
三、入棧地址高低問題
堆棧是在內(nèi)存中指定的一段特殊存儲(chǔ)區(qū),存起始單元的地址叫棧底,當(dāng)前存儲(chǔ)單元地址叫棧頂,堆棧存儲(chǔ)區(qū)一旦指定,棧底就固定不變了,而棧頂是隨入棧、出棧操作呈動(dòng)態(tài)。而不同機(jī)型的堆棧設(shè)計(jì),有兩種情況:一是每入棧一個(gè)數(shù),棧頂?shù)刂芳?,每出棧一個(gè)數(shù),棧頂?shù)刂窚p1,即堆棧區(qū)是由內(nèi)存的低地址向高地址。另一種是每入棧一個(gè)數(shù),棧頂?shù)刂窚p1,每出棧一個(gè)數(shù),棧頂?shù)刂芳?,即堆棧區(qū)是由內(nèi)存的高地址向低地址。高地址、低地址是相對(duì)而言,即相對(duì)地址編碼的大小而言。
轉(zhuǎn)載于:https://www.cnblogs.com/ablogia/p/3266321.html
總結(jié)
以上是生活随笔為你收集整理的大端模式小端模式、主机序网络序、入栈地址高低问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JUL
- 下一篇: usaco3.33Camelot(BFS