【C语言】枚举类型
00. 目錄
文章目錄
- 00. 目錄
- 01. 枚舉概述
- 02. 枚舉三種用法
- 03. 枚舉的本質
- 04. 枚舉與宏
- 05. 枚舉在Linux內核中應用
- 06. 使用枚舉需要注意的問題
- 07. 附錄
01. 枚舉概述
**枚舉(enum)**是C語言的一種特殊類型。當我們在編程中遇到定義一些固定長度或范圍的數值時,可以考慮使用枚舉類型。使用枚舉可以讓我們的程序可讀性更強、看起來更加直觀。舉個例子,如果我們在編程中需要使用數字0-6分別表示星期日-星期六,程序的可讀性就不高,我們需要翻手冊或者看程序注釋才能知道每個數字具體代表什么意思。如果我們使用枚舉呢,基本上不需要看注釋或手冊就可知曉其大意。
enum week // enum 枚舉類型{枚舉值列表}; {SUN,MON,TUE,WED,THU,FRI,SAT, }; enum week today = SUN; //使用枚舉類型定義一個變量使用enum定義的枚舉值列表中,默認值是從0開始,然后依次遞增:SUN=0,MON=1…。當然我們也可以顯式指定枚舉值:
enum week {SUN = 1,MON,TUE,WED,THU = 7,FRI,SAT, }; //SUN=1,那么接下來MON=2,TUE=3,WED=4 //THU=7,那么接下來FRI=8,SAT=902. 枚舉三種用法
使用枚舉類型定義變量,使用方法跟結構體、共用體類似,經常使用的三種方法如下:
enum week //定義枚舉類型的同時,定義枚舉變量 {SUN,MON,TUE,WED,THU,FRI,SAT, }today, tomorrow;enum //可以省去枚舉類型名,直接定義變量 {SUN,MON,TUE,WED,THU,FRI,SAT, }today, tomorrow;enum week //先定義枚舉類型,再定義枚舉變量 {SUN,MON,TUE,WED,THU,FRI,SAT, }; enum week today, tomorrow;03. 枚舉的本質
在C語言中,枚舉是一種類型,屬于整型的范疇,使用enum定義的枚舉值列表,其實就是從0開始的一系列整數序列。整型除了short、int、long、long long外,還包括char、_Bool(C99標準新增)和enum。因此,枚舉的使用其實和整數值其實沒啥區別:我們使用枚舉類型定義的變量,同樣可以作為函數參數、函數返回值、用來定義數組、甚至和結構體混用等。
enum week get_week_time (void); int set_week_time (enum week time_set); int change_week_time (enum week *p); enum week a[10]; struct student {char name[20];int age;enum week birthday; };枚舉有點類似于typedef,給一個數值添加一個別名,讓我們的程序更加直觀、可讀性更高。枚舉類型在本質上就是有命名的整數,屬于整型的一種,在代碼中是可以和整型互換的。
enum week t = SUN; int t2 = SUN; enum week t3 = t2; enum week t4 = 100;在上面的代碼中,枚舉變量和整型變量相互賦值,都是可以正常編譯和運行的。我們在代碼中使用枚舉類型,在最終編譯生成的可執行文件中都會被整型數值代替。
enum week {SUN = 5,MON,TUE,WED,THU,FRI,SAT, };int main (void) {enum week today = THU;return 0; }在上面的示例代碼中,我們定義了一個枚舉類型week,然后定義了一個枚舉變量today,并賦值為THU。反匯編上面的代碼,我們可以看到匯編代碼:
00010400 <main>:10400: e52db004 push {fp} 10404: e28db000 add fp, sp, #010408: e24dd00c sub sp, sp, #121040c: e3a03009 mov r3, #9 10410: e50b3008 str r3, [fp, #-8]10414: e3a03000 mov r3, #010418: e1a00003 mov r0, r31041c: e24bd000 sub sp, fp, #010420: e49db004 pop {fp} ;10424: e12fff1e bx lr在C程序中定義的枚舉變量today,在匯編代碼的第1040c處,我們可以看到:枚舉值THU被替換為整型數值9。使用枚舉的唯一好處就是增加代碼的可讀性,它的作用跟宏定義的作用有異曲同工之妙。
04. 枚舉與宏
枚舉與預處理指令#define的作用差不多,都是為了增加代碼的可讀性。但在實際使用中,兩者還是有些差別的:宏在預處理階段,通過簡單的字符串替換就全部被替換掉了,編譯器根本不知道有宏這么一個玩意;而枚舉類型則在編譯階段全部替換為整型。
跟宏相比,枚舉的優勢是:枚舉可以自動賦值,而宏則需要一個一個單獨定義。因此,在自定義一些有規則的類型值的時候,使用枚舉會更加方便。枚舉可以自定義的變量值來代替數字值,使我們的程序代碼有更高的可讀性。
05. 枚舉在Linux內核中應用
在Linux內核代碼中,充斥著大量的枚舉類型數據,有些枚舉類型的定義看起來很奇怪,比如:
enum {MM_FILEPAGES,MM_ANONPAGES,MM_SWAPENTS,NR_MM_COUNTERS }; enum pid_type {PIDTYPE_PID,PIDTYPE_PGID,PIDTYPE_SID,PIDTYPE_MAX };Linux內核中使用enum定義的枚舉類型大部分是沒有枚舉名的,而且通常會在一串枚舉值之后帶上一個NR*的元素用來表示枚舉值的數量。當我們不需要使用枚舉類型去定義一個枚舉變量時,枚舉并不需要一個名字,這些無名的枚舉類型其實就相當于宏定義。而最后一個元素NR或MAX,一般可以用來記載枚舉列表中元素的個數,或者作為循環判斷的邊界值。
06. 使用枚舉需要注意的問題
什么是類型?類型是一定范圍的數值及方法的集合。枚舉作為整型類型的一種,在編程使用過程中,也有一些注意的地方,比如作用域。使用枚舉定義的常量也遵循數據作用域規:包括文件作用域、代碼塊作用域等,在同一個作用域能不能出現重名的枚舉常量名。
enum week1 {SUN,MON,TUE,WED,THU,FRI,SAT, }; enum week2 {SAT,UNKNOW, }; int main (void) { return 0; }在上面的代碼中,我們定義了兩個枚舉類型,其中枚舉常量SAT重名,編譯時就會發生如下錯誤:
error: redeclaration of enumerator `SAT' error: previous definition of 'SAT' was here出現錯誤的原因是,我們定義的不同枚舉類型中的兩個枚舉常量名同在一個作用域:文件作用域,我們稍微改一下代碼就可以避免沖突:
#include <stdio.h> enum week1 {SUN,MON,TUE,WED,THU,FRI,SAT, }; int main (void) {printf("%d\n", SAT);enum week2{SAT,UNKNOW,};printf("%d\n", SAT); return 0; }我們將枚舉類型week2的定義放到了main函數內,week2的作用域就從文件作用域變為代碼塊作用域。這個時候,兩個枚舉類型中的同名枚舉常量就不會再發生沖突,程序的運行結果為:
6 007. 附錄
參考:C程序設計
總結
- 上一篇: 【嵌入式】C语言高级编程-可变参数宏(1
- 下一篇: 【Linux网络编程】广播