Appearance
题目
某计算机存储器按字节编址,采用小端方式存放数据。假定编译器规定 int 型和 short 型长度分别为 32 位和 16 位,并且数据按边界对齐存储。某 C 语言程序段如下:
c
struct {
int a;
char b;
short c;
} record;
record.a = 273;若 record 变量的首地址为 0xC008,则地址 0xC008 中存放的内容及 record.c 的地址分别为( )。
错因
A
两处错都出现了:
- 把 273 = 0x00000111 用大端方式存放——大端把高字节放低地址,所以 0xC008 处是 0x00、0xC00B 处才是 0x11。题目明写"小端",方向正好相反。
- 忽略了边界对齐——把 short c 紧贴 char b 后面放,c 的地址 = 0xC00D。但 short 要按 2 字节边界对齐,必须填 1 字节空位,c 的地址应为 0xC00E。
B
把 0xC008 处的内容算成 0x00 —— 同 A 的"大端方向"错。c 的地址 0xC00E 倒是对的(说明意识到了对齐,只是字节序记反了)。
C
字节序对了(小端 → 0xC008 处放 0x11),但 c 的地址错算成 0xC00D —— 漏了 1 字节填充。char b 占 1 字节(在 0xC00C),剩下 0xC00D 是为对齐而填的空位,short c 必须从 0xC00E 开始。
总解析
第一步:算出 a = 273 的 32 位机器数
写成 4 字节十六进制:
第二步:按小端方式把 a 摊到内存
小端规则:低字节放低地址,按字节从右到左依次填入升序地址。
| 地址 | 内容 |
|---|---|
| 0xC008(最低) | 0x11 |
| 0xC009 | 0x01 |
| 0xC00A | 0x00 |
| 0xC00B(最高) | 0x00 |
所以 0xC008 处存的就是 0x11。
第三步:算出 record.c 的地址(边界对齐)
按"自然对齐"规则——类型大小为 N 字节的成员,地址必须是 N 的倍数:
| 成员 | 类型 | 大小 | 对齐要求 | 实际占用区间 |
|---|---|---|---|---|
| a | int | 4 字节 | 4 字节对齐 | 0xC008 ~ 0xC00B |
| b | char | 1 字节 | 1 字节对齐 | 0xC00C |
| padding | — | 1 字节 | — | 0xC00D(填充 1 字节让 c 对齐) |
| c | short | 2 字节 | 2 字节对齐 | 0xC00E ~ 0xC00F |
为什么要 1 字节 padding?b 紧接 a 后从 0xC00C 开始(OK,char 无对齐要求);接下来 short c 需要 2 字节边界,0xC00D 不是 2 的倍数,必须跳到下一个 2 的倍数 = 0xC00E。
第四步:拼答案
- 0xC008 处内容 = 0x11
- record.c 的地址 = 0xC00E
最终答案是 D(0x11、0xC00E)。
两个判定要点速记:
- 小端 = 低字节存低地址("小尾巴 little-endian = 小数字(低位)放小地址")
- 大端反之,低位在高地址
- x86 / x64 是小端;网络字节序(TCP/IP)是大端
- 自然对齐 = 类型大小是几就按几对齐(int 按 4,short 按 2,char 按 1);compiler 在不对齐位置自动插 padding
编者注(格式修复):原题面在
record.a = 273;后断开,缺"若 record 变量的首地址为 0xC008,则地址 0xC008 中存放的内容及 record.c 的地址分别为( )"这句问题文字(OCR/抄写漏行),已按真题原文补回(首地址 0xC008 由四个选项的 c 地址倒推唯一确定)。