15.struct-vs-union.md 4.8 KB

struct vs union

判别规则(核心,唯一要记的)

  • struct → 成员累加(大小 = 成员之和 + 对齐填充),各成员同时有效
  • union → 成员共用(大小 = 最大成员,含其对齐),同一时刻只有一个有意义,写一个覆盖其他

一句话:"struct 各自有房(累加),union 共住一室(取最大)——struct 存同时需要的,union 存轮流用的。"

抽象描述(一句话本质)

struct 成员依次排开、各自独立;union 所有成员共用同一块内存。判别核心 = 成员"同时用还是轮流用"。union 三大用途:测大小端、省内存的变体消息、寄存器字节/字复用。

正反例(建立直觉)

  • 正例1struct S { char c; int i; }; → c、i 独立,sizeof = 8(含填充)
  • 正例2union U { char c; int i; }; → 共用同一地址,写 i 覆盖 c,sizeof = 4(最大成员)
  • 正例3(测大小端)union { int i; char c; } u; u.i = 0x12345678; u.c == 0x78 → 小端;0x12 → 大端(c 和 i 共用起始地址,读 c 看到最低字节)
  • 正例4(变体消息)union { struct A{...}; struct B{...}; uint8_t raw[6]; } → 不同协议共用一块 buffer,统一按 raw 收发再按 id 解析
  • 反例1:以为 union 能同时存所有成员 → 错,写一个覆盖另一个
  • 反例2:以为 union 大小 = 成员之和 → 错,是最大成员

易混对比

struct union
存储 依次排开,各自独立 共用一块,同一时刻用一个
大小 成员之和 + 填充 最大成员
写一个成员 不影响其他 覆盖其他成员
典型用途 组合数据 省内存、变体消息、大小端判断

大小端速查(union 测大小端的根基)

大小端 = 多字节数据在内存里的排列顺序。int i = 0x12345678

低地址字节 内存里看到 谁在用
小端 little-endian 存低字节 78 78 56 34 12 x86、ARM 主流
大端 big-endian 存高字节 12 12 34 56 78 网络协议、某些 CPU

union 原理:所有成员共享同一起始地址u.i = 0x12345678 后读 u.c(char 取一字节)= 最低地址字节 → 小端给 0x78、大端给 0x12。跨平台通信必须约定字节序,否则 A 存的低字节 B 按大端解读就变值了。

变体验证(3 题,全过=学会)

  1. union { char c; short s; int i; }; → sizeof = 4(最大成员 int)
  2. 陷阱题:union { int i; double d; }; → sizeof = 8(double 最大且对齐 8)
  3. 陷阱题:u.i = 10; 后再 u.c = 'a';u.i 不可靠(写 c 覆盖了 i 的内存)

口述要点(面试怎么讲)

  • 结论先行:struct 累加独立、union 共用覆盖;大小 = 最大成员
  • union 地址关系:所有成员共享同一起始地址 → 写 int 后读 char 能看到最低字节 → 这就是测大小端的原理
  • 大小端:小端低字节存低地址(内存看到 78 56 34 12),大端反之;x86/ARM 主流小端,网络协议常大端。union 测法:u.i=0x12345678;u.c 是 0x78 还是 0x12
  • 变体消息场景:不同协议 struct 封装 + union 统一一块 buffer + raw 数组统一收发,按 id 解析——省内存
  • 什么时候选 union:同一块内存当不同类型用(大小端、寄存器字节/字访问)、多个互斥字段省内存(状态机不同阶段数据);成员要同时有效 → 用 struct
  • 易错点:写一个成员覆盖其他;union 大小是最大成员不是累加

关系网络

相邻概念 和本主题的关系 孤立理解会犯的错
结构体对齐 大小计算同一套规则:union 大小 = 最大成员(含其对齐) 以为 union 也像 struct 累加
大小端 union 测大小端的原理 = 共用起始地址看最低字节 不懂字节序就看不懂 union 的这个用途
位域 都是压缩内存的手段 以为 union 和位域只能二选一
通信协议 变体消息:struct 封装各协议 + union 统一 buffer 不用 union 每个协议各开一块 buffer 浪费内存

学习日期

2026-08-03


每主题一页,复习时只翻本目录。