Note
这个结构体在 32 位系统上占多少字节?
按常见 32 位 ABI 逐步计算含 padding 的结构体大小,并解释为何结果是 20 字节。
省流
题目(32 位操作系统,按常见自然对齐):
struct mystr { char a; int b; char c[10]; };
sizeof(struct mystr)为 20 字节。
布局是:a占 1 字节,其后填 3 字节以对齐int;b占 4 字节;c[10]占 10 字节;结构体对齐为 4,末尾再填 2 字节,总和 1+3+4+10+2=20。
计算假设
以下按面试中最常见的 32 位约定:
| 类型 | 大小 | 对齐 |
|---|---|---|
char | 1 | 1 |
int | 4 | 4 |
char[10] | 10 | 1 |
结构体对齐 = 成员最大对齐 = 4。
结构体总大小必须是 4 的整数倍。
逐步排布
偏移 0 : char a // 1 字节,下一偏移 = 1
偏移 1..3 : padding // 为让 int 从 4 的倍数开始
偏移 4..7 : int b // 4 字节,下一偏移 = 8
偏移 8..17 : char c[10] // 10 字节,下一偏移 = 18
偏移 18..19 : tail padding // 18 不是 4 的倍数,补到 20
因此:
sizeof = 20
若不加尾部填充,大小会停在 18,则 struct mystr arr[2] 中第二个元素起始偏移为 18,其中的 int b 会落在未按 4 对齐的地址上。尾部填充正是为了保证数组元素仍然满足结构体对齐。
容易算错的点
- 只把
1 + 4 + 10 = 15相加,忽略全部 padding。 - 记得中间 3 字节,却忘了末尾 2 字节,得到 18。
- 把 64 位下
long/pointer的对齐习惯套到这道 32 位int题上。
验证思路
实际可用编译器打印:
printf("%zu\n", sizeof(struct mystr));
在对应的 32 位目标(或明确相同对齐规则的环境)下,应得到 20。若开启紧凑打包属性,结果可能变小,那已不是本题的默认布局。