[c]
struct student {
char name[20];
int age;
char sex;
char phone[15];
};
// sizeof = 40? 實際 44
// 若 phone[16] -> sizeof = 44? 實際 48
這就是**內存對齊**在作祟。CPU 訪問內存時,按字長(4/8 字節)對齊能顯著提升效率,編譯器自動插入填充字節。
int 4 字節 → 4 字節對齊;double 8 字節 → 8 字節對齊。[c]
struct A { char c; double d; char ch; };
// 最大基本類型 double(8) -> 對齊基準 8
// c: offset 0, size 1
// d: offset 8 (對齊到 8), size 8
// ch: offset 16, size 1
// 總大小 24 (尾部填充到 24,24%8==0)
[c]
struct B { double d; char c; char ch; };
// d: offset 0, size 8
// c: offset 8, size 1
// ch: offset 9, size 1
// 總大小 16 (c/ch 共用一個 8 字節槽,尾部填充到 16)
結論:將大類型集中放置、小類型聚合,可減少填充,節省內存。
[c]
struct score { float eng, math, comp; }; // 基本類型 float(4),對齊基準 4,大小 12
struct student {
char name[10]; // 數組,非基本類型
int age; // 基本類型 int(4)
char sex; // 基本類型 char(1)
struct score s; // 嵌套結構體,最大基本類型 float(4)
};
// 對齊基準 = max(int, float) = 4
// 逐個計算偏移,最終 sizeof = 28 (或 32 視編譯器)
[c]
union U { int i; char c; char str[9]; };
// 聯合體大小 = 最大成員(9) -> 對齊到 4 的倍數 = 12
struct S { int i; char c; char str[9]; };
// 結構體大小 = 4+1+9=14 -> 對齊到 4 的倍數 = 16
[c]
#pragma pack(push, 1) // 1 字節對齊(緊湊模式)
struct Packed { char c; int i; };
#pragma pack(pop)
// sizeof = 5,但訪問 i 可能觸發非對齊訪問異常(ARM)或性能下降(x86)
適用場景:網絡協議報文、文件格式、共享內存——需精確控制佈局,且確認目標平台支援非對齊訪問。
| 場景 | 對齊基準 | 總大小規則 |
|---|---|---|
| 基本類型結構體 | 最大基本類型尺寸 | 尾部填充至基準整數倍 |
| 含數組/嵌套結構體 | 所有基本類型中最大者 | 同上,嵌套體內部自行對齊 |
| 聯合體 | 最大成員尺寸 | 向上取整至基準整數倍 |
| 調整成員順序 | 不變 | 可減少填充,節省空間 |
| #pragma pack(n) | min(n, 類型自身對齊) | 緊湊佈局,慎用 |