結構的對齊 (Struct Member Alignment)
在 C++ 的 struct 或 class 裡宣告變數時,記憶體裡是如何分配裡面的變數的呢?
寫一個小程式來看看
#include <iostream>
using namespace std;
struct Test01
{
char c1;
int n;
char c2;
};
int main()
{
cout << "sizeof(Test01) = " << sizeof(Test01) << endl; //12
Test01 t1;
t1.c1 = 'a';
t1.c2 = 'b';
t1.n = 313249262; //這個數字的 16 進位是 12abcdee
char* pc1 = &t1.c1;
char* pc2 = &t1.c2;
int* pn = &t1.n;
system("pause");
return 0;
}
執行結果

為什麼?
char 占 1 個 byte
int 占 4 個 byte
char 占 1 個 byte
那為什麼 Test01 的 size 不是 6 而是 12 呢?
來看看它實際的記憶體分配


這原因就在於 32bit 電腦為了效率
一次會抓取 32bits (4 bytes)
也就是一次抓 4 格,效率會比較高
才會產生這種中間有空格的對齊方式 (Alignment)
為了效率犧牲了空間

而中間的空格
會是原本存在在裡面的值
程式不會對它做什麼處理
所以基本上我們可以不用理這些空格
我們來試試看調整 struct 裡變數的順序
#include <iostream>
using namespace std;
struct Test02
{
char c1;
char c2;
int n;
};
int main()
{
cout << "sizeof(Test02) = " << sizeof(Test02) << endl; //8
Test02 t2;
t2.c1 = 'c';
t2.c2 = 'd';
t2.n = 313249279; //這個數字的 16 進位是 12abcdff
char* pc1 = &t2.c1;
char* pc2 = &t2.c2;
int* pn = &t2.n;
system("pause");
return 0;
}
執行結果

來看看它實際的記憶體分配


雖然 struct 裡內容一樣
但是宣告的順序不同
就節省了空間
而且原本需要抓 3 次
現在只要抓 2 次
也節省了效能
那如果我不要這種對齊呢?有 2 個方法可以調整
方法1-從 Visual Studio 的專案屬性去調整
但是會讓整份專案都變成調整過後的對齊方式

方法2-在程式裡調整
可以只針對某個 struct 或 class 調整
#include <iostream>
using namespace std;
#pragma pack(push) //把原本的對齊設定 push 進 stack
#pragma pack(1) //把對齊設定設成 1
struct Test01
{
char c1;
int n;
char c2;
};
#pragma pack(pop) //把原本的對齊設定 pop 出來
int main()
{
cout << "sizeof(Test01) = " << sizeof(Test01) << endl; //6
Test01 t1;
t1.c1 = 'a';
t1.c2 = 'b';
t1.n = 313249262; //這個數字的 16 進位是 12abcdee
char* pc1 = &t1.c1;
char* pc2 = &t1.c2;
int* pn = &t1.n;
system("pause");
return 0;
}
執行結果



但建議還是不要去調整對齊方式比較好
如果你真的很在意空間的話
還是調整變數宣告的順序吧!
小提醒1:把 struct 改成 class ,結果一樣。
小提醒2:為什麼 int 在記憶體裡的值是這樣存?是因為 little-endian,這可以寫另一個主題。