嵌入式開發-枚舉詳解 朱有鵬 1.枚舉 m 1.1、枚舉是用來干嘛的? #include <stdio.h> // 這個枚舉用來表示函數返回值,ERROR表示錯,RIGHT表示對 enum return_value { ERROR, // 枚舉值常量是全局的,直接自己就可以用。 RIGHT, }; enum return_value func1(void); int main(void) { enum return_value r = func1(); if (r == RIGHT) // 不是r.RIGHT,也不是return_value.RIGHT { printf("函數執行正確\n"); } else { printf("函數執行錯誤\n"); } printf("ERROR = %d.\n", ERROR); // ERROR = 0 printf("RIGHT = %d.\n", RIGHT); // RIGHT = 1證明枚舉 //中的枚舉值是常量 return 0; } enum return_value func1(void) { enum return_value r1; r1 = ERROR; return r1; } 枚舉在C語言中其實是一些符號常量集。直白點說:枚舉定義了一些符號,這些符號的本質就是int類型的常量,每個符號和一個常量綁定。這個符號就表示一個自定義的一個識別碼,編譯器對枚舉的認知就是符號常量所綁定的那個int類型的數字。 枚舉中的枚舉值都是常量,怎么驗證? 枚舉符號常來那個來說,數字不重要,符號才重要。符號對應的數字只要彼此不相同即可,沒有別的要求。所以一般情況下我們都不會明確指定這個符號所對應的數字,而是讓編譯器自動分配。編譯器自動分配的原則是,從0開始依次增加,如果用戶自己定義了一個值,則從定義的那個值開始往后依次增加。 1.2、C語言為何需要枚舉 C語言沒有枚舉是可以的。使用枚舉其實就是對1、0這些數字進行符號化編碼,這樣的好處就是編程時可以不用看數字而直接看符號。符號的意義是顯然的,一眼可以看出。而數字所代表的含義除非看文檔或者注釋。 宏定義的目的和意義是,不用數字而用符號,從這里可以看出,宏定義和枚舉有內在聯系。宏定義和枚舉經常用來解決類似的問題,他們倆基本可以互換,但是有一些細微差別。 1.3、宏定義和枚舉的區別 枚舉是將多個有關聯的符號封裝在一個枚舉中,而宏定義是完全散的。什么情況下用枚舉?當我們要定義的常量是一個有限集合時(譬如一星期有7天,譬如一個月有31天,譬如一年有12個月····),最適合用枚舉。(其實宏定義也行,但是枚舉更好),不能用枚舉的情況下(定義的常量符號之間無關聯,或者無限的)用宏定義。 宏定義最先出現,用來解決符號常量的問題,后來人們發現有時候定義的符號常量彼此之間有關聯(多選一的關系),用宏定義來做雖然可以但是不貼切,于是乎發明了枚舉來解決這種情況。 1.4、枚舉的各種不同的定義形式 (1)定義方法1:定義類型和定義變量分離開 enum week { SUN, // SUN = 0 MON, // MON = 1; TUE, WEN, THU, FRI, SAT, }; enum week today; (2)定義方法2:定義類型的同時定義變量 enum week { SUN, // SUN = 0 MON, // MON = 1; TUE, WEN, THU, FRI, SAT, }today,yesterday; (3)定義方法3,定義類型的同時定義變量 enum { SUN, // SUN = 0 MON, // MON = 1; TUE, WEN, THU, FRI, SAT, }today,yesterday; (4)定義方法4:用typedef定義枚舉類型別名,并在后面使用別名進行變量定義 typedef enum week { SUN, // SUN = 0 MON, // MON = 1; TUE, WEN, THU, FRI, SAT, }week; (5)定義方法5:用typedef定義枚舉類型別名 typedef enum { SUN, // SUN = 0 MON, // MON = 1; TUE, WEN, THU, FRI, SAT, }week; 注意: (1)不能有重名的枚舉類型 即在一個文件中不能有兩個或兩個以上的enum被typedef成相同的別名。這很好理解,因為將兩種不同類型重命名為相同的別名,這會讓gcc在還原別名時遇到困惑。比如你定義了typedef int INT; typedef char INT; 那么INT代表的是int還是char呢? (2)不能有重名的枚舉成員 兩個struct類型內的成員名稱是可以重名的,而兩個enum類型中的成員卻不可以重名。因為struct類型成員的訪問方式為 變量名.成員,而enum成員的訪問方式為 成員名,因此若兩個enum類型中有重名的成員,那代碼中訪問這個成員時到底指的是哪個enum中的成員呢? 但是兩個#define宏定義是可以重名的,該宏名真正的值取決于最后一次定義的值。編譯器會給出警告但不會error。
|