枚舉類型enum詳解——C語言


enum

enum是C語言中的一個關鍵字,enum叫枚舉數據類型,枚舉數據類型描述的是一組整型值的集合(這句話其實不太妥當),枚舉型是預處理指令#define的替代,枚舉和宏其實非常類似,宏在預處理階段將名字替換成對應的值,枚舉在編譯階段將名字替換成對應的值,

我們可以將枚舉理解為編譯階段的宏,使用格式:

enum typeName{ valueName1, valueName2, valueName3, ...... };

typeName枚舉類型的名字,花括號里面的元素(枚舉成員)常量而不是變量,這個一定要搞清楚,因為枚舉成員的是常量,所以不能對它們賦值,只能將它們的值賦給其他的變量

 

枚舉類型(枚舉標簽)、枚舉成員(枚舉常量)、枚舉變量之間的區別

當枚舉類型和枚舉變量放在一起定義時,枚舉類型的名字(就是enum week中的week)可以省略不寫,意思是上圖的有兩種寫法

第一種:

enum week{Mon = 1, Tues, Wed, Thurs}num;

第二種:

enum {Mon = 1, Tues, Wed, Thurs}num;

這一點其實和結構體中的無名結構很相似,雖然定義枚舉類型變量和定義結構類型變量看起來很相似,但是兩者的區別還是蠻大的,一個結構體類型變量里面包含若干個成員,相當於一個打包好的快遞盒子,

而枚舉類型變量就不一樣了,枚舉類型變量不是一個包含若干個成員的集合,枚舉類型變量和int、char類型的變量其實差不多,只不過枚舉類型變量的賦值只能用自身的枚舉成員來賦值,以上面的例子來說,

num的賦值就只能用枚舉成員Mon、Tues、Wed、Thurs,而不能用其他枚舉類型的枚舉成員來賦值

 

定義枚舉變量和定義結構體變量相同,有兩種定義方法

第一種:(定義枚舉類型的同時定義枚舉變量)

enum week{Mon = 1, Tues, Wed, Thurs}num;

第二種:(先定義枚舉類型,再定義枚舉變量)

enum week{Mon = 1, Tues, Wed, Thurs}; enum week num;

 

枚舉類型的特點

下面將用不同的示例來說明枚舉類型的特點

示例一:(不顯式說明枚舉常量的值)

enum week{Mon, Tues, Wed, Thurs, Fri, Sat, Sun};

在沒有顯示說明的情況下,枚舉常量(也就是花括號中的常量名)默認第一個枚舉常量的值為0,往后每個枚舉常量依次遞增1,所以Mon=0,Tues=1,····Sun=6,下面來驗證一下

enum week{Mon, Tues, Wed, Thurs, Fri, Sat, Sun}; printf("Mon=%d\nTues=%d\nWed=%d\nThurs=%d\nFri=%d\nSat=%d\nSun=%d\n", Mon, Tues, Wed, Thurs, Fri, Sat, Sun);

運行結果:

 

示例二:(顯示說明部分枚舉常量的值)

enum week{Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun};

上面的代碼中,只顯式說明了枚舉常量Mon的值為1,未指定的枚舉名的值將依着最后一個指定值向后依次遞增(注意是最后一個指定值)

enum week{Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun}; printf("Mon=%d\nTues=%d\nWed=%d\nThurs=%d\nFri=%d\nSat=%d\nSun=%d\n", Mon, Tues, Wed, Thurs, Fri, Sat, Sun);

運行結果:

 

對上面的代碼稍加修改

enum week{Mon = 1, Tues, Wed, Thurs, Fri = 10, Sat, Sun}; printf("Mon=%d\nTues=%d\nWed=%d\nThurs=%d\nFri=%d\nSat=%d\nSun=%d\n", Mon, Tues, Wed, Thurs, Fri, Sat, Sun);

運行結果:

 

示例三:(對枚舉變量進行賦值)

enum week{Mon = 1, Tues, Wed, Thurs}num; num = (enum week)10; printf("%d", num);

一個整數不能直接賦值給一個枚舉變量,必須用該枚舉變量所屬的枚舉類型進行類型強制轉換后才能賦值上面的代碼中,在對枚舉變量賦值10的時候進行的強制類型轉換,將整型常量10轉換成了enum week類型再賦值給num變量,

運行結果:

 

總結:

1、在沒有顯示說明的情況下,枚舉常量(也就是花括號中的常量名)默認第一個枚舉常量的值為0,往后每個枚舉常量依次遞增1

2、在部分顯示說明的情況下,未指定的枚舉名的值將依着之前最有一個指定值向后依次遞增

3、一個整數不能直接賦值給一個枚舉變量,必須用該枚舉變量所屬的枚舉類型進行類型強制轉換后才能賦值

4、同一枚舉類型中不同的枚舉成員可以具有相同的值

5、同一個程序中不能定義同名的枚舉類型,不同的枚舉類型中也不能存在同名的枚舉成員(枚舉常量)

 

enum與typedef配合使用

typedef enum week my;

或者

typedef enum week{Mon = 1, Tues, Wed, Thurs}my;

上面typedef也可以省略week

typedef enum{Mon = 1, Tues, Wed, Thurs}my;

上面兩種形式中,my都是enum week的別名(意思是my和enum week等價),需要注意的是如果將第二句的typedef去掉那么my就變成了enum week類型的變量,如果加上typedef那么my就是enum的別名,這點要注意區分

在定義了enum week的別名my后,后面就可以使用my來定義枚舉類型變量

my num; num = (enum week)10; printf("%d", num);

上述語句中的(enum week),可以改為(my),兩者效果是一樣的

補充:對上面總結的第五點:同一個程序中不能定義同名的枚舉類型,不同的枚舉類型中也不能存在同名的枚舉成員(枚舉常量)進行驗證

enum m1{m1, m2}; enum m2{m3, m4}; enum m1{m5, m6};

 

上述代碼定義的枚舉類型enum m1多次定義,是不允許的,編譯器會報錯還有一種特殊情況,即使定義了同名的枚舉類型,編譯器也不會報錯

enum m1{m1, m2}; enum m2{m3, m4}; enum m1;

 

上面的代碼中,第二個enum m1沒有定義枚舉成員,在編譯階段是不會報錯的(估計是編譯器並不認為定義了枚舉成員的enum m1 和 沒有定義枚舉成員的enum m1是同名的枚舉類型

 

enum的賦值范圍

這個也是無意間注意到的,文章在開頭提到枚舉類型描述的是一組整型值的集合,枚舉類型的占的字節數是4個字節,所以我們可以用INT_MAX和INT_MIN來測試枚舉類型的賦值范圍,賦值的最大值應該是INT_MAX(也就是2147483647),下面用代碼來測試一下

enum test{m1=INT_MAX}; printf("%d\n%d\n", m1, INT_MAX);

 

運行結果:

 

上面的代碼沒有問題,下面來測試一下越界的賦值

enum test{m1=INT_MAX+1}; printf("%d\n%d\n", m1, INT_MAX);

 

 編譯器在編譯階段會有警告測試了枚舉類型的最大值,下面來測試下枚舉類型的最小值

 

enum test{m1=INT_MIN};
printf("%d\n%d\n", m1, INT_MIN);

 

 

 

運行結果:

上面的代碼沒有問題,下面來測試一下越界的賦值

enum test{m1=INT_MIN-1}; printf("%d\n%d\n", m1, INT_MIN);

 

和上面相同,編譯器也會有警告

 

為什么“枚舉類型描述的是一組整型值的集合”其實不太妥當?

上面這句話很容易讓讀者以為enum類型和int類型是等價的,好像可以把int型的數據直接賦值給enum變量,實際上是不行的,需要進行強制類型轉換,C語言提供了一種稱為“枚舉”的類型,其中一個枚舉常量的占的字節數為4個字節,恰好和int類型的變量占的字節數相同,假設把這些枚舉常量說明為整型,字符型或其他類型顯然是不妥當的,因為枚舉類型是一種基本數據類型,而不是一種構造類型,它不能再分解為什么基本類型

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM