## struct vs union ## 判别规则(核心,唯一要记的) - **struct** → 成员**累加**(大小 = 成员之和 + 对齐填充),各成员同时有效 - **union** → 成员**共用**(大小 = 最大成员,含其对齐),同一时刻只有一个有意义,写一个覆盖其他 一句话:**"struct 各自有房(累加),union 共住一室(取最大)——struct 存同时需要的,union 存轮流用的。"** ## 抽象描述(一句话本质) struct 成员依次排开、各自独立;union 所有成员共用同一块内存。判别核心 = 成员"同时用还是轮流用"。union 三大用途:测大小端、省内存的变体消息、寄存器字节/字复用。 ## 正反例(建立直觉) - **正例1**:`struct S { char c; int i; };` → c、i 独立,sizeof = 8(含填充) - **正例2**:`union 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 --- _每主题一页,复习时只翻本目录。_