排序不同,會造成sizeof整個struct的值不同。
例如以下的例子:
struct aaaaa
{
char a;
int b;
char c;
};
-byte數為12-
struct aaaaa
{
char a;
char c;
int b;
};
-byte數為8-
========== START ==========
struct 的 alignment 有兩個, 首先是個別成員的 alignment, 然後是整個 struct 的 alignment.
首先, 每一個類型都會有它自己的 alignment requirement. 每個物件在記憶體裏的相對位置是:
Offset % alignment-requirement == 0
假定在你的編譯器上, char 的 alignment requirement 是 1, int 的 alignment requirement 是 4.
在第一個 struct 裏, a 是在 offset 0 的位置, 而 b 則須在 offset 4 的位置. a 跟 b 之間會有 3 個 byte 的空格.
個別成員的 alignment 完成後就要做整個 struct 的 alignment. 這個關係到最後一個成員後面要加多少個 padding. 需要這個的原因是當你以 struct 來定義一個陣列的時候, 每一個 struct 元素都需要 align. 這時就要以到 struct 裡面最大的成員來做決定.
所以第一個 struct 最後一個成員 c 後面需要 3 個 bytes 的 padding. 這樣在陣列的架構下, 下一個元素的 b 也會 align:
+=======+
0 |a|x|x|x|
|-------|
4 |b |
|-------|
8 |c|x|x|x|
+=======+
12 |a|x|x|x|
|-------|
16 |b |
|-------|
20 |c|x|x|x|
+=======+
| |
第二個 struct 的 padding 結構:
+=======+
0 |a|c|x|x|
|-------|
4 |b |
+=======+
8 |a|c|x|x|
|-------|
12 |b |
+=======+
而要解決此問題,最好在每一個struct裡面都放相同alignment的變數,
或是使用#pragma pack ()
A1:
#pragma pack(push, 1)
struct aaaaa
{
char a;
char c;
int b;
};
#pragma pack(pop)
其中 "push" 的意思是先將原來的設定(可能是 4)暫存起來;而 "pop" 則是恢復原來的設定。
A2:
#pragma pack(1)
struct aaaaa
{
char a;
char c;
int b;
};
#pragma pack(1)
意思是說,強制把alignment設定為1 byte
參考資料:
Visual C++ 的 Struct Memeber Alignment 問題與解決方法
C/C++ struct 的 alignment
沒有留言:
張貼留言