內存對齊其實是為了在程序運行的時候更快的查找內存而做的一種編譯器優化。
我們先看這樣一個例子:
1 #include <iostream> 2 using namespace std; 3 4 struct vpoet 5 { 6 int a; //4 bytes 7 char b; //1 bytes 8 double c; // 8 bytes 9 char *d; //4 bytes 10 int e; //4 bytes 11 }; 12 13 int main() 14 { 15 cout<<"sizeof(vpoet)="<<sizeof(vpoet)<<endl; 16 return 0; 17 }
運行結果:
這個結構體大小為24個字節,但是我們仔細算一算其字節數發現其實際上只有4+1+8+4+4=21個字節,那是如何算出來24個字節的
呢,其實在默認情況下編譯器是按照結構體中所占字節最大的成員來進行內存對齊的。比如在結構體vpoet中最大的是double double
占8個字節,那么編譯器默認按8個字節的方式對齊那么編譯器將按照大於實際字節數的double最小整數倍來進行內存分配。因而這里
實際是在結構體的成員b后面填充了三個字節用於對齊。
那么問題來了,對齊方式可以改嗎?可以我們可以在文件頭加上
1 #pragma pack(n)
來改變內存對齊的字節數
比如當我們按照一個字節對齊的時候:
1 #include <iostream> 2 using namespace std; 3 #pragma pack(1) 4 5 struct vpoet 6 { 7 int a; //4 bytes 8 char b; //1 bytes 9 double c; // 8 bytes 10 char *d; //4 bytes 11 int e; //4 bytes 12 }; 13 14 int main() 15 { 16 cout<<"sizeof(vpoet)="<<sizeof(vpoet)<<endl; 17 return 0; 18 }
運行結果:
當我們按照1字節對齊的時候,編譯器將為該結構體分配本身實際大小的字節數
當我們以2字節對齊的時候
1 #pragma pack(2)
此時的輸出結果為:
當我們按照2字節對齊的時候,編譯器將為結構體成員b后面填充一個空字節用於內存對齊。
記住這樣一個規律:
默認情況下編譯器將按照實際結構體中占內存字節數最大的成員的整數倍進行分配,該最大的整數倍應正好大於或者等於結構
體實際所占的內存字節數