枚举
枚举
一、什么是枚举?
enum 用来给一组相关的整数值定义有意义的名字。
enum Color
{
RED = 0,
GREEN,
BLUE
};默认情况下,后面的枚举值会在前一个值的基础上递增:
RED = 0
GREEN = 1
BLUE = 2也可以手动指定:
enum Color
{
RED = 10,
GREEN = 20,
BLUE = 30
};使用:
enum Color color = GREEN;二、枚举的本质
在 C 语言中,枚举常量本质上是整数常量。
而枚举类型的底层整数类型由编译器决定,通常会选择能够表示该枚举值的整数类型。
因此不要简单记成:
enum永远就是int。
更准确的理解是:
枚举是一种整数类型,用名字代替具体的整数值,提高代码的可读性和可维护性。
例如:
if (state == STATE_RUNNING)明显比:
if (state == 2)更容易理解。
三、枚举在嵌入式中的常见用途
1. 状态机
enum State
{
STATE_IDLE,
STATE_RUNNING,
STATE_ERROR
};使用:
enum State state = STATE_IDLE;特别适合:
- 状态机
- 工作状态
- 连接状态
- 设备状态
2. 错误码
enum Error
{
ERR_OK = 0,
ERR_TIMEOUT,
ERR_BUSY,
ERR_FAILED
};比直接使用:
if (ret == 2)更加直观。
3. 配置选项
enum Mode
{
MODE_NORMAL,
MODE_LOW_POWER,
MODE_DEBUG
};四、枚举值的范围
不要用:
“枚举就是
int,所以一定只能到INT_MAX。”
来理解枚举。
枚举值首先需要满足 C 语言对枚举常量表达式的要求,而枚举类型的具体表示方式由实现决定。
例如:
enum Number
{
A = 100,
B = 100000
};具体占用多少存储空间,应以编译器的实现为准。
因此在嵌入式开发中,如果你特别关心:
这个变量到底占几个字节?
直接使用:
sizeof(enum Number)进行验证,而不要凭感觉判断。
五、不要把枚举当成严格的取值限制
例如:
enum State
{
IDLE,
RUNNING,
ERROR
};
enum State state = 100;C 语言对枚举类型的检查比较宽松,并不像 C++ 的 enum class 那样提供强类型约束。
因此:
枚举主要解决的是“名字”和“可读性”问题,而不是运行时的数据范围检查。
如果需要严格限制取值,仍然需要自己进行检查。
六、枚举和 enum class 的区别
C++ 中:
enum class Color
{
RED,
GREEN,
BLUE
};属于更强类型的枚举。
例如:
Color c = Color::RED;不能像传统 C 风格枚举那样随意与普通整数进行隐式转换。
因此:
C enum
↓
类型检查较宽松
↓
更偏向“给整数起名字”
C++ enum class
↓
强类型
↓
更严格的类型安全七、枚举到底占几个字节?
不要写:
enum Color
{
RED,
GREEN,
BLUE
};然后直接认为:
sizeof(enum Color) == 1或者一定等于:
sizeof(int)具体大小由编译器实现决定。
如果需要确认:
printf("%zu\n", sizeof(enum Color));在 STM32 工程中还应该结合具体的:
- 编译器
- ABI
- 编译选项
来判断。
如果协议、Flash 存储或硬件寄存器明确要求固定宽度,不要依赖 enum 的大小,应该显式使用:
uint8_t
uint16_t
uint32_t八、枚举常量数量有限制吗?
C 标准会规定实现至少需要支持一定数量的枚举常量,但实际编译器通常远远超过这个最低要求。
所以工程上一般不需要担心:
enum
{
A,
B,
C,
...
};“枚举名字太多”这种问题。
真正需要考虑的是:
枚举是否真的能让代码更清晰。
如果把大量完全无关的常量全部塞进一个枚举,反而会降低代码可读性。
九、核心理解
把 enum 记成:
enum
↓
一组相关的整数值
↓
给这些整数值起有意义的名字
↓
提高代码可读性嵌入式中最常见的就是:
状态机
错误码
工作模式
配置选项
协议状态一句话记忆:
枚举的核心不是“定义几个数字”,而是把一组具有明确语义的整数值组织起来,用名字表达它们的含义。

