Appearance
题目
在按字节编址,采用小端方式的 32 位计算机中,按边界对齐方式为以下 C 语言结构型变量 a 分配存储空间。
c
struct record {
short x1;
int x2;
} a;若 a 的首地址为 2020FE00H,a 的成员变量 x2 的机器数为 12340000H,则其中 34H 所在存储单元的地址是( )。
错因
A
两个错叠加:① 没考虑边界对齐——以为 x2 紧跟 x1 后从 0x2020FE02 起 ② 把存储方式当成大端——大端时 0x12340000 从高位字节起:0x02:12, 0x03:34, 0x04:00, 0x05:00。所以 34H 在 0x2020FE03。"无对齐 + 大端" 双重错。
B
按"无边界对齐 + 小端"算:x2 从 0x2020FE02 起,小端 0x12340000 = 字节 [00, 00, 34, 12],落在 0x02, 0x03, 0x04, 0x05;34H 在 0x04。错在没做边界对齐——int 必须从 4 字节边界开始。
C
按"对齐 + 大端"算:x2 起始 0x2020FE04(对齐了),大端时字节 [12, 34, 00, 00],34H 在 0x05。错在把存储方式判成大端。题目明说"小端"。
总解析
第一步:明确两个关键约束
- 边界对齐:int(4 字节)必须从地址为 4 的倍数的位置开始
- 小端:低字节存低地址(数据按字节"反着"存)
第二步:确定 x1 和 x2 的起始位置
a 首地址 = 0x2020FE00。
| 字段 | 类型 | 大小 | 边界要求 | 起始地址 | 占用范围 |
|---|---|---|---|---|---|
| x1 | short | 2 | 2 字节 | 0x2020FE00 | 0x00 ~ 0x01 |
| 填充 (padding) | — | 2 | — | 0x2020FE02 | 0x02 ~ 0x03 |
| x2 | int | 4 | 4 字节 | 0x2020FE04 | 0x04 ~ 0x07 |
为什么 x2 在 0x04 而不是 0x02:
按字段顺序 x2 紧跟 x1 后应当在 0x02。但 int 要求 4 字节边界对齐——起始地址必须是 4 的倍数。0x02 不是 4 的倍数(最小符合的下一个对齐地址是 0x04),所以编译器在 x1 和 x2 之间插入 2 字节填充 padding,让 x2 落到 0x04。
第三步:把 x2 = 0x12340000 按小端拆字节
小端规则:最低字节存最低地址。0x12340000 按字节从低到高:
| 字节序号 | 字节值 |
|---|---|
| B0(最低字节) | 00 |
| B1 | 00 |
| B2 | 34 |
| B3(最高字节) | 12 |
写入内存:
| 地址 | 值 |
|---|---|
| 0x2020FE04 | 00 |
| 0x2020FE05 | 00 |
| 0x2020FE06 | 34 |
| 0x2020FE07 | 12 |
34H 所在地址 = 0x2020FE06。
最终答案是 D(2020FE06H)。
完整内存布局图:
| 地址 | 内容 | 说明 |
|---|---|---|
| 0x2020FE00 | x1 低字节 | x1 (short) 起 |
| 0x2020FE01 | x1 高字节 | |
| 0x2020FE02 | 00(padding) | 填充对齐 |
| 0x2020FE03 | 00(padding) | 填充对齐 |
| 0x2020FE04 | 00 | x2 (int) 起 = 4 字节边界 |
| 0x2020FE05 | 00 | |
| 0x2020FE06 | 34 | ← 命中 |
| 0x2020FE07 | 12 | x2 末(最高字节) |
易错点速查:
- 边界对齐:int 起始地址必须是 4 的倍数(不是紧跟前一字段)
- 边界对齐造成的 padding 填充不算数据,但占地址空间
- 小端:低字节在低地址(0x12340000 倒着存 = 00, 00, 34, 12)
- 对齐 + 小端 = "起始位置对齐到 4,再按小端摆字节"两步都不能少