从基础 → 底层实现 → 嵌入式应用 全面掌握这两个概念。
🧩 一、共用体(union)的本质与定义
1️⃣ 基本概念
共用体(union)和结构体(struct)很像 ,但它们在内存上的工作方式 完全不同。
| 特性 | struct | union |
|---|---|---|
| 各成员都有独立的内存 | ✅ 是 | ❌ 否(共享同一段内存) |
| 内存大小 | 所有成员大小之和 | 最大成员的大小 |
| 同时保存多个值 | 可以 | 只能保存一个成员的值 |
2️⃣ 示例对比
c
#include <stdio.h>
struct S {
int a;
char b;
};
union U {
int a;
char b;
};
int main() {
struct S s = {65, 'B'};
union U u;
u.a = 65;
printf("struct大小: %zu\n", sizeof(s));
printf("union大小: %zu\n", sizeof(u));
u.b = 'B';
printf("u.a = %d, u.b = %c\n", u.a, u.b);
return 0;
}
🧠 运行结果(假设 64 位系统)
struct大小: 8
union大小: 4
u.a = 66, u.b = B
解释:
- 共用体的所有成员共享同一块内存。
- 当
u.b = 'B'时,它其实覆盖了前面的 int 值。 - 所以
u.a的值被修改了(65 → 66,因为字符'B'的 ASCII 是 66)。
3️⃣ 内存图解
text
union U {
int a; // 占 4 字节
char b; // 占 1 字节
}
内存(假设起始地址 0x1000):
| 地址 | 内容 | 说明 |
|---|---|---|
| 0x1000 | a 或 b 的值 | 共用同一位置 |
| 0x1001 | 同上 | ... |
| 0x1002 | 同上 | ... |
| 0x1003 | 同上 | ... |
⚙️ 二、嵌入式实际用途:硬件寄存器映射
在嵌入式开发中,共用体经常用于:
- 查看数据的不同表现形式
- 访问寄存器的不同位段
1️⃣ 多视角访问同一块数据
c
union Data {
int i;
unsigned char bytes[4];
};
int main() {
union Data d;
d.i = 0x12345678;
printf("bytes: %02X %02X %02X %02X\n",
d.bytes[0], d.bytes[1], d.bytes[2], d.bytes[3]);
return 0;
}
✅ 输出(取决于大小端):
bytes: 78 56 34 12
📘 用途:
- 快速查看变量在内存中的布局;
- 网络协议中做 大小端转换(endian swap);
- 将一个整数打包成字节流。
2️⃣ 寄存器位操作映射
嵌入式芯片中,寄存器通常是一个 32 位的值,但不同位控制不同功能。
可以这样定义:
c
typedef union {
unsigned int ALL; // 整体访问寄存器
struct {
unsigned int EN :1; // bit0: 使能
unsigned int MODE :2; // bit1~2: 模式
unsigned int STATUS :1; // bit3: 状态
unsigned int RESERVED:28;
} BIT;
} REG_CTRL;
int main() {
REG_CTRL reg;
reg.ALL = 0; // 清零
reg.BIT.EN = 1; // 使能寄存器
reg.BIT.MODE = 3; // 模式选择
printf("寄存器值: 0x%08X\n", reg.ALL);
}
✅ 输出:
寄存器值: 0x00000007
🧠 优点:
- 结构化访问硬件寄存器;
- 无需复杂位操作;
- 可读性与安全性都提升。
🔤 三、typedef ------ 类型重命名神器
1️⃣ 基础用法
typedef 是 "type definition" 的缩写,用来 给类型起别名。
c
typedef unsigned int uint32;
typedef struct {
int x;
int y;
} Point;
现在可以写成:
c
uint32 a = 10;
Point p = {1, 2};
2️⃣ typedef + struct/union 常用写法
写结构体/共用体时,我们常见三种方式:
c
struct A { int x; }; // 方式1:声明结构体类型
typedef struct A AType; // 方式2:起别名
typedef struct { int x; } B; // 方式3:匿名结构体 + typedef
方式3 最常用于嵌入式开发:
c
typedef struct {
uint8_t EN;
uint8_t MODE;
} CTRL_REG;
3️⃣ typedef + 函数指针(非常常见)
c
typedef void (*ISRHandler)(void);
现在可以直接定义:
c
ISRHandler Reset_ISR;
而不是:
c
void (*Reset_ISR)(void);
🧠 四、嵌入式实战案例:结构体 + 共用体 + typedef
c
typedef union {
unsigned int ALL;
struct {
unsigned int TXE:1;
unsigned int RXE:1;
unsigned int ERR:1;
unsigned int RESERVED:29;
} BIT;
} UART_STATUS;
typedef struct {
UART_STATUS STATUS;
unsigned char DATA;
} UART_REG;
UART_REG *UART1 = (UART_REG *)0x40011000; // 寄存器基址映射
int main(void) {
if (UART1->STATUS.BIT.RXE) {
unsigned char data = UART1->DATA;
printf("接收数据: %c\n", data);
}
}
✅ 说明:
- 用
typedef让结构体定义更简洁; - 用
union既能按位访问,又能整体访问; - 在嵌入式系统中直接映射寄存器地址,效率极高。
📘 五、总结对比表
| 概念 | struct | union | typedef |
|---|---|---|---|
| 内存独立 | 每个成员独立占空间 | 所有成员共用空间 | 不影响内存,仅起别名 |
| 用途 | 数据组织 | 内存复用、位操作、硬件寄存器 | 类型简化、可读性提升 |
| 嵌入式意义 | 模块化数据 | 寄存器映射 | 统一风格、提高可维护性 |