內存對齊以及如何按任意字節內存對齊


內存對齊以前有接觸過,最近又碰到好幾次,特整理記錄一下。

首先為什么需要內存對齊?

內存對齊(memory alignment).為了提高程序的性能,數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在於,為了訪問未對齊的內存,處理器需要作兩次內存訪問;然而,對齊的內存訪問僅需要一次訪問。也就是說“內存對齊”應該是編譯器的管轄范圍,非常依賴平台。

先來看下面的結構體:

1 struct _Test{  
2     int a;  
3     int b;  
4     char c;  
5 }A;

sizeof(A)=?(32位機器)

在32位機器上,如果內存對齊,sizeof(A)=12。

那么如何讓機器按任意字節呢?

有兩種方式:添加預處理指令 #pragma pack(1) 或者 __attribute__ ((packed))

1 添加預處理指令 #pragma pack(1)

#paragma pack(1)預處理指令的作用是結構體在分配內存時按一個字節對齊。

 1 #include<stdio.h>  
 2 #pragma pack(1)  
 3 struct _Test{  
 4     int a;  
 5     int b;  
 6     char c;  
 7 }A;  
 8 void main()  
 9 {  
10     printf("sizeof(A) = %d\n",sizeof(A));  
11 } 

輸出結果 就是9。

這里說明一下,如果用了#paragma pack(1)預處理指令,則整個文件中都會關閉內存對齊,如果只想對其中某個或某幾個結構其關閉呢,這是就要用到第二種方法了。

2  利用__attribute__ ((packed))指令

 1 #include<stdio.h>  
 2 //#paragma pack(1)  
 3 struct _TestA{  
 4     int a;  
 5     int b;  
 6     char c;  
 7 }__attribute__ ((packed))A;  
 8 
 9 struct TestB{  
10     int a;  
11     int b;  
12     char c;  
13 }B;  
14  
15 void main()  
16 {  
17     printf("%d\n",sizeof(A));  
18     printf("%d\n",sizeof(B));  
19 } 

輸出結果是 9  12

但是__attribute__ ((packed))這種語法只能在GCC下編譯通過,Visual Sudio不支持這種語法,編譯不過(僅在VS2008測試過,更高版本是否支持沒有測試)。

3. 如果想在Visual Sudio下也能編譯,可以采用下面這種方法

 1 #include<stdio.h>  
 2 
 3 #pragma pack(push)
 4 #pragma pack(1)
 5 struct _TestA{  
 6     int a;  
 7     int b;  
 8     char c;  
 9 }A;  
10 #pragma pack(pop)
11 
12 struct TestB{  
13     int a;  
14     int b;  
15     char c;  
16 }B;  
17 
18 void main()  
19 {  
20     printf("sizeof(A) = %d\n",sizeof(A));  
21     printf("sizeof(B) = %d\n",sizeof(B));  
22 }

輸出結果是 9  12。

其實就是在不使用默認內存對齊的結構提前加上 #pragma pack(push) #pragma pack(1) ,然后在結束的地方加上 #pragma pack(pop) 

 


免責聲明!

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



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