一句话:"偏移必须能整除自己的对齐值,总大小必须能整除最大对齐值。"
CPU 按"对齐值"访问内存最省事——4 字节对齐一次读 4 字节。编译器在成员间插填充字节,让每个成员偏移 = 自身对齐值整数倍;结构体总大小 = 最大对齐值整数倍。对齐是拿空间换速度,pack 是拿速度换空间。
struct A { char c; int i; char d; }; → c@0、i@4(补 3)、d@8,用满 9 → 补到 12。sizeof(A) = 12(不是 6)struct B { char c; char d; int i; }; → c@0、d@1 紧挨、i@4,sizeof(B) = 8。同样三个成员 A=12、B=8 → 从大到小排最省空间offsetof(struct A, i) = 4,offsetof(struct A, d) = 8| 默认对齐 | #pragma pack(1) |
|
|---|---|---|
| 填充 | 有(按成员对齐值) | 无(强制 1 字节对齐) |
| 大小 | 更大(浪费但快) | 最小(省空间但慢) |
| 适用 | 普通内存结构 | 通信协议帧、Flash 存储 |
struct { char c; int i; char d; }; → sizeof = 12(c@0、i@4、d@8,补到 12)struct { char a; char b; short s; }; → sizeof = 4(两个 char 挨着 0、1,s@2,共 4)#pragma pack(1) 下 struct { char c; int i; }; → sizeof = 5(无填充,1+4)| 相邻概念 | 和本主题的关系 | 孤立理解会犯的错 |
|---|---|---|
| union | union 大小 = 最大成员(对齐值最大者),共用一块 | 以为 union 也像 struct 累加 |
| 位域 | 位域也是压缩内存的手段,但可移植性差 | 以为对齐和位域互斥 |
| 程序分段 | 对齐决定段内数据怎么摆 | 以为分段和段内布局无关 |
| 通信协议 | pack(1) 保证结构体 = 协议帧 | 不用 pack 导致双方解析错位 |
2026-08-03
每主题一页,复习时只翻本目录。