C/C++ 結構體大小不單純等於成員大小總和,編譯器為了存取效率會依照對齊規則插入填補位元組。VC++(MSVC)預設採用「成員對齊到其大小,整體結構對齊到最大成員大小」的規則。本文透過實例詳細推導計算過程。
| 型別 | 大小 | 對齊需求 |
|---|---|---|
| char | 1 | 1 |
| short | 2 | 2 |
| int / long / float | 4 | 4 |
| double / long double | 8 | 8 |
| 指標 | 4 | 4 |
#pragma pack(n) 改變封裝大小(1,2,4,8,16)。struct A { char c; long l; };
// 佈局:
// offset 0: c (1 byte)
// offset 1-3: padding (3 bytes) → 使 l 對齊到 4
// offset 4: l (4 bytes)
// 總計 8 bytes
sizeof(A) == 8
struct B { char c; long l; short s; };
// offset 0: c (1)
// offset 1-3: pad (3)
// offset 4: l (4)
// offset 8: s (2)
// offset 10-11: tail pad (2) → 結構對齊到 4 的倍數 (12)
sizeof(B) == 12
struct C { char c; short s; long l; };
// offset 0: c (1)
// offset 1: pad (1) → s 對齊 2
// offset 2: s (2)
// offset 4: l (4)
// 總計 8 bytes(無尾端填補)
sizeof(C) == 8 — 成員順序影響大小!
struct Data1 {
int i; // 4 @0
char ch; // 1 @4
double d; // 8 @8 (需對齊 8,故 ch 後填補 3)
short s; // 2 @16
float f; // 4 @18 → 對齊 4 需填補 2 → @20
long l; // 4 @24
};
// 總計 28 → 尾端對齊 8 → 32
sizeof(Data1) = 32
struct Data2 {
short s1; // 2 @0
char ch1; // 1 @2
short s2; // 2 @4 (ch1 後填補 1)
char ch2; // 1 @6
};
// 尾端對齊 2 → 8
sizeof(Data2) = 8
struct Data3 {
int i; // 4 @0
char ch1; // 1 @4
short s2; // 2 @6 (ch1 後填補 1)
char ch2; // 1 @8
};
// 尾端對齊 4 → 12
sizeof(Data3) = 12
#pragma pack(push, 1) // 1 位元組封裝,無填補
struct Packed { char c; long l; };
#pragma pack(pop)
sizeof(Packed) == 5; // 但存取 long 可能觸發對齊錯誤或效能下降
offsetof(Data1, d) 應為 8。