枚举(enum)详解及其使用指南
目录
一、初阶
建立一个枚举类型:
枚举的初始化及使用:
二、进阶
不使用枚举变量的写法:
使用枚举变量的写法:
三、高阶
一、初阶
建立一个枚举类型:
typedef enum { IDLE = 0, RUNNING, PAUSE,//最后这个逗号写不写都可以 }STATUS;
可以指定某个成员的值,其后的成员依次加1,不指定则从0开始。指定的值可以是负数,但一定是整数
枚举的初始化及使用:
STATUS st = IDLE;
只能取枚举类型里的成员
!!!!在这里顺便聊聊变量初始化的问题,一般全局变量未初始化默认0,局部变量默认0或者随机值,比如说在GCC10.2.0编译环境下,局部变量就是一个随机值,如下:
void Print(STATUS st) { switch (st) { case IDLE: printf("IDLE\r\n"); break; case RUNNING: printf("RUNNING\r\n"); break; case PAUSE: printf("PAUSE\r\n"); break; default: printf("other\r\n"); break; } } int main(void) { STATUS st; Print(st); return 0; }
所以切记,不管全局变量还是局部变量,一定要初始化
二、进阶
不使用枚举变量的写法:
在很多场景下,我习惯写成如下:
enum { IDLE = 0, RUNNING, PAUSE, };
这样写之后不能用此枚举类型来声明变量,但可以类似于当#define使用。
对于同一个类型的数据,我们把他们重新命名一下,便于阅读和记忆,这就是枚举的重要作用。还有一种常用的情况是配合数组使用。
enum { IDLE = 0, RUNNING, PAUSE, ST_NUM, }; u8 arr[ST_NUM]; arr[IDLE] = 10; //用枚举成员名访问数组
我们在定义数组的时候,直接用该枚举类型的最后一个值作为数组大小,下次要增加或者减少参数的时候就不用去改数组大小了,非常方便。同时还可以用成员名当数组索引去访问数组元素。
使用枚举变量的写法:
使用枚举变量,就写成上面typedef的形式。
多使用枚举变量,能增强程序的鲁棒性,但程序的通用性会变差,主要体现在传参和赋值中。
这里以u8(无符号char型)和枚举之间的传参举例:
int main(void) { u8 st = 1; Print(st); return 0; }
换成10
int main(void) { u8 st = 10; Print(st); return 0; }
可见把一个u8的实参放入一个枚举的形参是可以的,反过来把一个枚举的实参放入u8的形参也是可以的,并且编译器不会警告。
那赋值勒,我们把一个u8赋给一个枚举:
int main(void) { STATUS st; u8 a = 1; st = a; Print(st); return 0; }
可见赋值也是可以的,反过来把一个枚举赋给u8也成立且不会报警告(我在KEIL上如果把u8赋值给枚举需要强转,不然会报警告)。
由此我么看出,在传参和赋值过程中枚举中的成员可以视为一个数值,可以自由的与其他变量进行值传递,但要注意一个就是值截断(把u32赋给u8就会发生值截断)。
!!!!这里就不得不聊聊枚举变量的大小,它占用几个字节勒。
我查阅资料得出:enum类型的大小是由编译器根据定义值的大小来选择合适的整数类型,所以enum类型的大小并不是固定的。
一般编译器来说enum的大小为4个字节,超过了编译器就会把它的大小扩大到8个字节。例如:
typedef enum { IDLE = 0x1122334455, RUNNING, PAUSE, ST_NUM, }STATUS;
小技巧:
对了,还可以拿枚举来定义命令码
enum { CMD_1 = 0XEA, CMD_2 = 0XEB, CMD_3 = 0XEE, };
三、高阶
高阶的我也不会,一会儿也想不完整,以后再慢慢补充到这篇文章里来吧,欢迎大家评论
作者:小鱼儿的小笔记