枚举的引入

枚举是C语言中的一种基本数据类型,它可以让数据更简洁,更易读。

枚举语法定义格式为:

​​​​​​​enum 枚举名{枚举元素1,枚举元素2,…… //注意,各元素之间用逗号隔开};//注意,末尾有分号;

枚举是用来干嘛的?
枚举在C语言中其实是一些符号常量集。直白点说:枚举定义了一些符号,这些符号的本质就是int类型的常量,每个符号和一个常量绑定。这个符号就表示一个自定义的一个识别码,编译器对枚举的认知就是符号常量所绑定的那个int类型的数字。
一般情况下我们都不明确指定这个符号所对应的数字,而让编译器自动分配。

编译器自动分配的原则是:从0开始依次增加。如果用户自己定义了一个值,则从那个值开始往后依次增加。

C语言为何需要枚举?

C语言没有枚举是可以的。使用枚举其实就是对一些数字进行符号化编码,这样的好处就是编程时可以不用看数字而直接看符号。符号的意义是显然的,一眼可以看出。而数字所代表的含义除非看文档或者注释。

这么看来,宏定义也能实现呀!要专门弄个枚举类型干嘛?

宏定义和枚举有内在联系,宏定义和枚举经常用来解决类似的问题,他们俩基本相当可以互换,但是有一些细微差别。

宏定义和枚举的区别:
1、枚举是将多个有关联的符号封装在一个枚举中,而宏定义是完全散的。也就是说枚举其实是多选一,而且只能在这里面选,有时候有效防止其他不符数据的输入。
2、什么情况下用枚举?当我们要定义的常量是一个有限集合时(譬如一星期有7天,譬如一个月有31天,譬如一年有12个月····),最适合用枚举。(其实宏定义也行,但是枚举更好)
3、不适合用枚举的情况下(比如定义的常量符号之间无关联,或者无限的)用宏定义。

宏定义示例:

#define MON1#define TUE 2#define WED3#define THU 4#define FRI5#define SAT 6#define SUN 7

枚举示例:

enum DAY{ MON=1, TUE, WED, THU, FRI, SAT, SUN};

总结:宏定义先出现,用来解决符号常量的问题;后来人们发现有时候定义的符号常量彼此之间有关联(多选一的关系),用宏定义来做虽然可以但是不贴切,于是乎发明了枚举来解决这种情况。

类型定义和变量声明

枚举类型需要先定义后使用,这里的定义是类型的定义,不是枚举变量的定义。

既然枚举也是一种数据类型,那么它和基本数据类型一样也可以对变量进行声明。

方法一:枚举类型的定义和变量的声明分开

//先定义类型enum DAY//类型名称就是enum DAY{MON=1, TUE, WED, THU, FRI, SAT, SUN};//后声明变量enum DAY yesterday;enum DAY today;enum DAY tomorrow; //变量tomorrow的类型为枚举型enum DAYenum DAY good_day, bad_day; //变量good_day和bad_day的类型均为枚举型enum DAY

方法二:类型定义与变量声明同时进行

enum //跟第一个定义不同的是,此处的标号DAY省略,这是允许的。{saturday,sunday = 0,monday,tuesday,wednesday,thursday,friday} workday; //变量workday的类型为枚举型enum DAY//变量days的类型为枚举型enum weekenum week { Mon=1, Tue, Wed, Thu, Fri Sat, Sun} days; //定义枚举类型并声明了两个枚举型变量enum BOOLEAN { false, true } end_flag, match_flag; 

第二种方式的变量定义是一次性的,后面要想再定义同类型变量就不行了。

第一种方式更灵活。

方法三:用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明

typedef enum workday{saturday,sunday = 0,monday,tuesday,wednesday,thursday,friday} workday; //此处的workday为枚举型enum workday的别名//或者//enum workday中的workday可以省略typedef enum{saturday,sunday = 0,monday,tuesday,wednesday,thursday,friday} workday; //此处的workday为枚举型enum workday的别名//定义变量//变量today和tomorrow的类型为枚举型workday,也即enum workdayworkday today, tomorrow; 

注意:

同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常量。

使用枚举变量

1、先声明后赋值(常用)

#include/* 定义枚举类型 */enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };void main(){/* 使用基本数据类型声明变量,然后对变量赋值 */int x, y, z;x = 10;y = 20;z = 30;/* 使用枚举类型声明变量,再对枚举型变量赋值 */enum DAY yesterday, today, tomorrow;yesterday = MON;today = TUE;tomorrow= WED;printf("%d %d %d \n", yesterday, today, tomorrow);}

就像各种类型都有取值范围一样,枚举变量只能接收枚举类型中定义好的符号值(实质是一个int类型的数据)。

2、声明的同时赋值

#include /* 定义枚举类型 */enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };void main(){/* 使用基本数据类型声明变量同时对变量赋初值 */int x=10, y=20, z=30;/* 使用枚举类型声明变量同时对枚举型变量赋初值 */enum DAY yesterday = MON,today = TUE, tomorrow = WED;printf("%d %d %d \n", yesterday, today, tomorrow);}

3、类型定义、变量声明和赋值同时进行(不推荐,会引入全局变量)

#include /* 定义枚举类型,同时声明该类型的三个变量,并赋初值。它们都为全局变量 */enum DAY{MON=1, TUE,WED,THU,FRI,SAT,SUN }yesterday = MON, today = TUE, tomorrow = WED;/* 定义三个具有基本数据类型的变量,并赋初值。它们都为全局变量 */int x = 10, y = 20, z = 30;void main(){printf("%d %d %d \n", x, y, z); //输出:10 20 30printf("%d %d %d \n", yesterday, today, tomorrow); //输出:1 2 3}

补充

对枚举型的变量可以直接赋任意整数值,如果赋值浮点数,也会自动去掉小数部分。

赋整数值时,可直接赋值,因为枚举的本质就是整型(int)数据的集合。

#include int main(){enum week{MON, TUE, WEN};enum week oneday = 100;printf("%d,Hello, World! \n", oneday); //100,Hello, World! }

其实,更正规的做法是进行显式的强制类型转换:

#include int main(){enum week{MON, TUE, WEN};enum week oneday = (enum week)100;printf("%d,Hello, World! \n", oneday); //100,Hello, World! }

但是不强制转换也可以,和第一个示例一样,不加的话就是隐式类型转换,不会出错。

枚举变量既可以定义变量使用,也可以直接使用:

#include int main(){enum week{MON, TUE, WEN};enum week oneday = MON;printf("%d,Hello, World! \n", oneday); //0,Hello, World! printf("%d,Hello, World! \n", WEN);//2,Hello, World!}

直接使用枚举的情况更常见,因为一旦通过变量,那么就可以赋任何值,那就失去了枚举的意义了,本来枚举就是为了放一些特定整数集合的数据类型,值一般是固定的,比如对错、比如星期、比如状态等等。