也談linux中cpu大小端問題


內存對齊問題之大小端對齊問題

郝東東

 

所謂的大小端問題,也就是字節序。處理器(CPU)對內存數據操作有兩種模式:讀和寫。這樣,處理器在讀寫一個多字節內存的時候,高字節是在內存的高地址還是低地址就是一個問題,不同的大小端模式可能有不同的結果。

當處理器讀寫指令針對數據不一致的時候就涉及到大小端問題,例如:將0x7654321放入內存里,然后在內存首地址用單字節讀取命令,這就涉及到處理器是大端還是小端。對於小端處理器,寫內存的時候會將內存的低地址處放入數據源的低字節,在內存的高地址處放入數據源的高字節;大端模式則剛好相反。這個可以參照下面這個例子:

 

 1 Char c1,c2,c3,c4;
 2 
 3 Unsigned char *p;
 4 
 5 Unsigned long a=0x76543210;
 6 
 7 P=(unsigned char *)&a;
 8 
 9 C1=*p;
10 
11 C2=*(p+1);
12 
13 C3=*(p+2);
14 
15 C4=*(P+3);

這樣的話,可以輸出這四個值,在小端處理器運行的時候:c1=0x10;c2=0x32;c3=0x54;c4=0x76;這是由於在儲存a的時候,需要4個連續的字節,小端模式最低的字節將被放置在內存的最低位。0x10被放置在第一個字節。同理大端模式則相反。C4=0x10;

下面介紹幾種方法,可以直接判斷我們的電腦是什么模式儲存數據:第一種方案:利用聯合體。程序如下:

 1 #include<stdio.h>
 2 
 3 #include<stdlib.h>
 4 
 5 int cpu_return()
 6 
 7 {
 8 
 9    union perk
10 
11    {
12 
13       int a;
14 
15       char b;
16 
17    }c;
18 
19    c.a==1;
20 
21    return(c.b==1);
22 
23 }
24 
25  
26 
27 int main()
28 
29 {
30 
31    printf("%d\n",cpu_return());
32 
33 }

返回0則是小端模式,1是大端模式。

 

第二種方案:構造共用體,用長整型來訪問,依次輸出每個字節,程序如下:

 1 #include<stdio.h>
 2 
 3 #include<stdlib.h>
 4 
 5 typedef struct byte_4
 6 
 7 {
 8 
 9    unsigned char byte0;
10 
11    unsigned char byte1;
12 
13    unsigned char byte2;
14 
15    unsigned char byte3;
16 
17 }byte4;
18 
19 typedef union data32
20 
21 {
22 
23    unsigned long data;
24 
25    byte4 databyte;
26 
27 }data_32;
28 
29 int main(void)
30 
31 {
32 
33    data_32 a;
34 
35    a.data=0x11223344;
36 
37    printf("databyte(0,1,2,3):(%x,%x,%x,%x)\n",a.databyte.byte0,a.databyte.byte1,a.databyte.byte2,a.databyte.byte3);
38 
39    return 0;
40 
41 }

小端輸出為:databyte(0,1,2,3):(44,33,22,11)

大端輸出為:databyte(0,1,2,3):(11,22,33,44)

 

第三種方案直接看最低位儲存的值來判斷:

 1 #include<stdio.h>
 2 
 3 #include<stdlib.h>
 4 
 5 int testcpu()
 6 
 7 {
 8 
 9    unsigned int x=1;
10 
11    if(1==*(unsigned char *)&x)
12 
13    printf("Little Endian\n");
14 
15    else
16 
17    printf("Big Endian\n");
18 
19    return(1==*(unsigned char *)&x);
20 
21 }
22 
23 int main()
24 
25 {
26 
27    printf("CPU:%d\n",testcpu());
28 
29    return 0;
30 
31 }

小端返回1,大端返回0; 

 

最后,linux中網絡編程中要特別注意大小端問題,因為網絡字節序和本機字節序通常是需要轉換的,比如判斷一個udp報文是否為dhcp報文,需要將報文中的udp端口進行字節序轉換,通常調用ntohs去轉換后才可以判斷和賦值。

 


免責聲明!

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



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