enum
是 enumerate(列举,枚举)一词的缩写,是 C 语言中的一种常量,被称为 enumeration constant。enum
提供了一种很方便的方法来将值和名称关联起来,是#define
的一种替代方法。
enum
可以看作是一种特殊的数组,是常量组成的列表,而且这个常量只能是整数型。
所以如果是寥寥几个不相关、不连续的常量,直接定义几个常量就可以。但是如果是相关的或者连续的,使用enum
效率更高。
但是枚举与数组、元组不同的有 3点:
- 枚举并不是使用下标来定位元素值,而是使用关键字;
- 不同的
enum
中的值可以相同,但是名称必须不同; enum
的默认值为0, 1, 2...
,而数组是按照类型默认为其空值或者0
。
上面这段没看明白的话,可以看看下面的例子和代码就可以理解了。
严谨来说,这里不称作“关键字(keyword)”,而是“名称(name)”。因为在第一本广泛使用的 C 语言说明书《The C Programming Language》中,原文就是“name”一词。
下面是最常见的,也是在网上最常见的一种案例,以此为例开始详细介绍:
enum months {Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
网上给出的使用方法如下(有点复杂,但是现实中,在这种情况下并不推荐这种方法,后面说简洁的):
int main()
{
enum months mon; /* 声明month是months中的一个值,需要注意这里的mon是变量 */
int mon = Jan; /* mon的值等于Jan表示的值 */
printf("%d\n",mon); /* 输出mon的值 */
return 0;
}
这里输出的结果是0
。是因为没有定义名称表示的值,所以就按照默认值0, 1, 2...
,而Jan
是第一个,也就是0
。
那么如果我们想这个枚举中的名称对应的值是其月份呢?
你肯定会想,枚举嘛,那就一个个等于就好了。这样确实可以,但是这里的月份是连续的整数,所以不用一个个等于,只把第一个Jan=1
即可,如下:
enum months {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
这样不光输出Jan
得到的是1
,而且输出Sep
得到的9
,不用一个个等于那么麻烦。
看到这里你可能会想,必须要弄一个mon
来获取值嘛?因为通过变量来获取常量的值,在很多情况下就挺多此一举的。
这里不光mon
不是必须的,连months
都不是必须的,因为enum
其实是常量的集合,区分内容是通过常量的名称,而不是enum
的名字。下面举个例子:
#include<stdio.h>
enum {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
enum {Mon=1, Tue, Wed, Thur, Fri, Sat, Sun};
int main()
{
printf("%d, %d\n", Mon, Jan);
return 0;
}
输出结果为:
1, 1
那么什么时候使用第一种方法,什么时候使用第二种呢?
文章最开头说过,enum
是一种常量。一般人并不会让一个变量简简单单等于一个常量,然后再输出这个变量,就为输出常量的值,而是直接输出常量就行。
所以绝大部分情况直接使用第二种即可,因为名称是不会重复的。第一种方法是为了一些特殊情况。比如说,如果你想函数返回值有 4 种情况(实际情况可能更多),每个情况表示的顺序的整数值为0, 1, 2, 3
,如下:
enum state {Standard, Error, Position_1, Position_2}
这时候代码可以写成(这里简化了很多,只是为了表示这种情况):
int test() {
enum state ret
if (...) {
ret = Standard
} else if (...) {
ret = Error
} else if (...) {
ret = Position_1
} else if (...) {
ret = Position_2
}
return ret
}
这样在某些情况下更方便。
2024-06-16 更新
最近在看《A Tour of C++ 3rd》的时候发现 C 和 C++ 的 enum虽然使用起来比较相似,但是目的却略有不同。C++11 增加了一些特性,区别可见《C++中的enum(枚举)是什么,以及与C中enum的不同之处》
希望能帮到有需要的人~