ARM存儲格式之 大端小端(徹底明白大端小端)

ARM存儲格式之 大端小端http://blog.csdn.net/asda56/article/details/36919809


我們知道在內存中數據是以字節爲單位進行存儲的,每個地址單元對應着一個字節(byte),一個字節爲8位(bite)。但是很多時候數據除了8bit額char外,還有16bit的short,32位的long型(要看具體的編譯器),必然存在多字節安排的問題。不同的計算機存放多字節值的順序不同,有些機器在起始地址存放低位字節(低位先存),即小端模式;有的機器在起始地址存放高位字節(高位先存),即大端模式。基於Intel的CPU,採用的是低位先存。而KEIL C51則爲大端模式。大端小端對應着數據在存儲器中的存放順序。

  同時,在網絡傳輸中,網絡協議需要指定網絡字節順序,TCP/IP協議中使用16位整數和32位整數的高位先存模式,對應我們的大端模式。

  下面是兩個具體例子:

  16bit寬的數0x1234在Little-endian模式(以及Big-endian模式)CPU內存中的存放方式(假設從地址0x4000開始存放)爲:

內存地址 小端模式存放內容 大端模式存放內容
0x4000 0x34 0x12
0x4001 0x12 0x34

  32bit寬的數0x12345678在Little-endian模式以及Big-endian模式)CPU內存中的存放方式(假設從地址0x4000開始存放)爲:

內存地址 小端模式存放內容 大端模式存放內容
0x4000 0x78 0x12
0x4001 0x56 0x34
0x4002 0x34 0x56
0x4003 0x12 0x78

  聯合體union的存放順序是所有成員都從低地址開始存放,利用該特性可以輕鬆地獲得了CPU對內存採用Little-endian還是Big-endian模式讀寫。

  寫程序判斷處理器是Little-endian模式,還是Big-endian模式,可以通過以下程序:

  1>.通過將int強制類型轉換成char單字節,通過判斷起始存儲位置。

1 void main(int argc, char **argv) 
2
 
3
 int i = 1
4
 char *cp = (char *)&i; //前面是指針運算符*,前值類型轉換。後面是取地址符號。 
5   if (*cp) //如果此時cp指向的內存爲1的話,則爲小端,否則爲大端。 
6   printf("Little Endian\n"); 
7
 else 
8
 printf("Big Endian\n"); 
9
 
10 exit(EXIT_SUCCESS); 
11
 }

註釋:如果小端方式中(i佔至少兩個字節的長度)則i所分配的內存最小地址那個字節中就存着1,其他字節是0.大端的話則1在i的最高地址字節處存放,char是一個字節,所以強制將char型量p指向i則p指向的一定是i的最低地址,那麼就可以判斷p中的值是不是1(或者爲0,也即是假)來確定是不是小端。

或者如下程序:

void main()
{
short int
 x;

char
 x0,x1;

x
=0x1122
;

x0
=((char*)&x)[0]; //低地址單元

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

if (0x11 == x0 && 0x22 == x1)
{
cout 
<< "Big_endian" <<
 endl;
}
else

{
cout 
<< "Little_endian" << endl;
}
}

2>.利用聯合體union的存放順序是所有成員都從低地址開始存放,判斷處理器模式。

bool checkCPU( )


union w 

int
 a; 
char
 b; 

} c; 
c.a 
= 1

return(c.b ==1
);

}

以及如下程序:

bool isLittleEndian()
{
union _dword
{
int
 all;
struct
 _bytes
{
char
 byte0; 
char pad[3
]; 
}bytes;
}dword;

dword.all
=0x87654321
;

return (0x21==
dword.bytes.byte0); 
}

分析:如果你的處理器調用函數isLittleEndian返回1,那麼說明你的處理器爲little endian,否則爲big endian.注意,如果在little endian處理器上,byte0和pad按內存從低到高的存放順序:LOW->byte0 pad[0] pad[1] pad[2] ->HIGH;0x87654321按內存從低到高的存放順序:  0x21  0x43   0x65   0x87, 可見byte0對應到0x21。所以通過判斷dword中第一個字節dword.bytes.byte0是否與0x21相等就可以看出是否是little endian。

 

 

 PS:本文後面幾個程序都是從網上摘抄過來的,對於聯合體Union不是很清楚的可以參看http://blog.sina.com.cn/s/blog_3fa943920100ob37.html 我覺得這篇博文寫的很詳細。通過本文對大端小端模式有了一個比較深的理解吧。也希望對讀者有些許幫助,謝謝!接下來我會總結下聯合Union結構和Struct的區別


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章