天天看點

大端模式&小端模式 主機序&網絡序

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的情況下存放為:

  資料 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的資料,資料解釋自然出錯。

  

四、引用他人的

<a target="_blank" href="http://blog.csdn.net/xuyanbo2008/article/details/7458007">http://blog.csdn.net/xuyanbo2008/article/details/7458007</a>

一、大端模式&amp;小端模式

所謂的“大端模式”,是指資料的低位(就是權值較小的後面那幾位)儲存在記憶體的高位址中,而資料的高位,儲存在記憶體的低位址中,這樣的存儲模式有點兒類似于把資料當作字元串順序處理:位址由小向大增加,而資料從高位往低位放;

所謂的“小端模式”,是指資料的低位儲存在記憶體的低位址中,而資料的高位儲存在記憶體的高位址中,這種存儲模式将位址的高低和資料位權有效地結合起來,高位址部分權值高,低位址部分權值低,和我們的邏輯方法一緻。

如果将一個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*)&amp;x)[0]; //低位址單元

x1=((char*)&amp;x)[1]; //高位址單元

若x0=0x11,則是大端; 若x0=0x22,則是小端......

上面的程式還可以看出,資料尋址時,用的是低位位元組的位址

二、主機序&amp;網絡序

不同的

cpu 有不同的位元組序類型這些位元組序是指整數在記憶體中儲存的順序這個叫做主機序,最常見的有兩種: 

1、little endian :将低序位元組存儲在起始位址 

2、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 &lt;-----x86系統是小端位元組序系統

motorola680x()          全部    big endian

mips                     nt       little endian

mips                    unix    big endian

powerpc                  nt     little endian

powerpc                 非nt    big endian   &lt;-----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 *)(&amp;i)) ? true : false;

}

int main()

   if(am_little_endian())

            printf("本機位元組序為小段序!\n");

else

          printf("本機位元組序為大段序!\n");

        return 0;

三、入棧位址高低問題

堆棧是在記憶體中指定的一段特殊存儲區,存起始單元的位址叫棧底,目前存儲單元位址叫棧頂,堆棧存儲區一旦指定,棧底就固定不變了,而棧頂是随入棧、出棧操作呈動态。而不同機型的堆棧設計,有兩種情況:一是每入棧一個數,棧頂位址加1,每出棧一個數,棧頂位址減1,即堆棧區是由記憶體的低位址向高位址。另一種是每入棧一個數,棧頂位址減1,每出棧一個數,棧頂位址加1,即堆棧區是由記憶體的高位址向低位址。高位址、低位址是相對而言,即相對位址編碼的大小而言。