C++ -結構的對齊

結構的對齊 (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,這可以寫另一個主題。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *