C++ 枚举(enum)与联合体(union)全解析——从内存到底层机制全面掌握 - 详解
目录
承接我上篇文章关于数据结构:结构体、类、枚举和联合体做的拓展,详细介绍了枚举(enum)以及联合体(union)的内容:
一、前言
在 C++ 的派生数据类型中,enum(枚举)与 union(联合体)虽然都属于用户自定义类型,但它们的用途、底层机制和语义完全不同:
枚举(enum):是一组具名的整数常量,提升代码可读性。
联合体(union):让多个成员共享同一块内存,实现类型复用和节省空间。
本篇文章将用示例和内存图带你一口气吃透这两个概念。
二、枚举(enum)——可读性与类型安全的常量集合
1️⃣ 枚举的定义
枚举类型用于定义一组命名的整数常量,语法如下:
enum 枚举名 {
常量名1 [= 整型常量],
常量名2 [= 整型常量],
...
};
要点:
枚举成员本质上是
int类型常量。如果不赋值,系统默认从 0 开始递增。
如果中间赋值,后面从上一个值继续递增。
2️⃣ 示例:自动与手动赋值
#include
using namespace std;
enum Color { RED, GREEN = 5, BLUE };
int main() {
cout << "RED = " << RED << ", GREEN = " << GREEN << ", BLUE = " << BLUE << endl;
return 0;
}
输出:
RED = 0, GREEN = 5, BLUE = 6
解释:
| 名称 | 是否赋值 | 实际值 | 说明 |
|---|---|---|---|
| RED | 否 | 0 | 第一个默认 0 |
| GREEN | 是 | 5 | 显式赋值 |
| BLUE | 否 | 6 | 从上一个(5)继续 +1 |
3️⃣ 稍复杂例子:断点递增
enum Week {
MON, // 0
TUE, // 1
WED = 10, // 10
THU, // 11
FRI, // 12
SAT = 20, // 20
SUN // 21
};
int main() {
cout << MON << " " << TUE << " " << WED << " " << THU
<< " " << FRI << " " << SAT << " " << SUN << endl;
}
输出:
0 1 10 11 12 20 21
4️⃣ 枚举的本质:具名的整数常量
其实,编译器会把它当成下面这样的宏常量:
const int RED = 0;
const int GREEN = 5;
const int BLUE = 6;
这样你在写代码时就不必记“魔法数字”,直接写 if (state == RED) 更易懂。
5️⃣ C++11 的强类型枚举(enum class)
C++11 引入了 enum class,解决传统枚举类型安全性差的问题。
enum class Color { RED, GREEN = 5, BLUE };
int main() {
Color c = Color::BLUE;
cout << static_cast(c) << endl; // 输出 6
}
区别对比:
| 特性 | 传统 enum | 强类型 enum class |
|---|---|---|
| 定义方式 | enum Color {RED, GREEN}; | enum class Color {RED, GREEN}; |
| 作用域 | 全局,可直接用 RED | 需Color::RED |
| 可隐式转 int | ✅ 是 | ❌ 否 |
| 类型安全 | ❌ 弱 | ✅ 强 |
| 用途 | 简单常量集合 | 更安全的枚举类型 |
✅ 小结:枚举的核心特性
| 特性 | 描述 |
|---|---|
| 默认从 0 开始递增 | 手动赋值会打断计数 |
| 底层是整型常量 | 可以直接输出或比较 |
| enum class 更安全 | 避免命名冲突与隐式转换 |
| 常用于状态机/模式枚举 | 如机器人状态、传感器状态等 |
三、联合体(union)——共享内存的多态数据结构
1️⃣ 定义与原理
联合体(union)与结构体类似,但所有成员共用同一段内存。
union 名称 {
类型1 成员1;
类型2 成员2;
...
};
关键特性:
所有成员从同一个地址开始。
大小 = 最大成员的大小。
同一时间只能有效存储一个成员的值。
2️⃣ 示例:共享内存效果
#include
using namespace std;
union Data {
int i;
float f;
char c;
};
int main() {
Data data;
data.i = 10;
cout << "i = " << data.i << endl;
data.f = 3.14;
cout << "f = " << data.f << endl;
cout << "i (after f assigned) = " << data.i << endl; // 同块内存被覆盖
}
输出:
i = 10
f = 3.14
i (after f assigned) = 1078523331
3️⃣ 内存图示(关键理解)
假设联合体的大小为 4 字节:
┌────┬────┬────┬────┐ │ byte0 │ byte1 │ byte2 │ byte3 │ └────┴────┴────┴────┘ ↑ i, f, c 都从这个位置开始
data.i = 10→ 内存:0A 00 00 00data.f = 3.14→ 内存被覆盖成:DB 0F 49 40再读
data.i→ 把浮点的二进制当作整数读 →1078523331
4️⃣ 典型应用场景
| 场景 | 示例 | 说明 |
|---|---|---|
| 节省内存 | 嵌入式、通信协议 | 一段数据多种解释方式 |
| 协议帧解析 | 同一数据字段可为 int 或 float | |
| 类型重解释 | 读取相同字节内容的不同类型 | |
| 字节序分析 | 查看系统大端/小端存储 |
5️⃣ 示例:类型重解释(float ↔ int)
#include
using namespace std;
union Converter {
int i;
float f;
};
int main() {
Converter conv;
conv.f = 3.14;
cout << "float: " << conv.f << endl;
cout << "as int: " << conv.i << endl;
}
输出:
float: 3.14
as int: 1078523331
说明:
3.14的二进制表示(IEEE754)为0x40490FDB。当用
int读取同一内存时,就会看到一个大整数。
✅ 小结:联合体的核心特性
| 特性 | 说明 |
|---|---|
| 所有成员共享同一块内存 | 同地址不同解释 |
| 大小 = 最大成员的大小 | 节省空间 |
| 不能同时保存多个值 | 写入一个会覆盖另一个 |
| 常用于底层解析 | 通信、嵌入式、驱动层 |
四、枚举 vs 联合体 对比总结
| 对比项 | 枚举(enum) | 联合体(union) |
|---|---|---|
| 本质 | 一组具名整型常量 | 共享内存的多成员结构 |
| 占用内存 | 各常量无存储 | 按最大成员大小分配 |
| 使用目的 | 提高可读性 | 节省空间或重解释数据 |
| 值类型 | 整型常量 | 可为任意类型 |
| 是否共用内存 | ❌ 否 | ✅ 是 |
| C++11 增强 | enum class | 无新语法,但可嵌套类内 |
| 典型场景 | 状态机、模式标识 | 通信协议、嵌入式设备 |
| 底层行为 | 常量递增规则 | 字节级内存共享 |
五、结语
✨ 一句话总结:
enum:让整数常量有名字,提升代码可读性与可维护性。
union:让多个成员共用同一内存,是底层程序设计的节省空间利器。

浙公网安备 33010602011771号