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