摘要:在C語言的編程中,我們常常需要定義一些常量,此時是采用宏定義還是采用枚舉類型呢?它們有哪些區別?本文主要探討這個問題。
一、作用域對比
1.1宏定義的默認作用域為整個文件,如果定義了宏定義結尾的地方,作用域就到那個地方;這裡有一個潛在的危險,如果我們的頭文件中包含了宏定義,此時會導致宏定義沒有按照程序員的意願而產生了范圍擴展,當在另外的文件中有了相同的宏定義以後,就會產生沖突導致編譯無法通過。
在C語言編程中,對一個比較大型的項目,用到的庫會比較多,如果設計的稍有疏忽,便可能產生宏定義的沖突。項目中有一個例子就是發生在兩個頭文件都定義了“ISSPACE(ch)”這個宏,並且兩個宏定義不太一致,從而導致了整個工程無法編譯。
解決該問題的方法是將該宏undefine,具體的做法是,在緊鄰include語句之後對有沖突的宏進行undefine。例如庫liba.h和頭文件 app_pub.h就有對ISSPACE (ch)的不同定義,如果同時使用這兩個文件,就會產生宏定義的沖突,這時,可以將其一個undefine(一個前提是,不是兩個頭文件定義的宏都會用到):
#include "app_pub.h"
#ifdef ISSPACE
#undef ISSPACE
#endif
這樣的方法是解決宏定義沖突的一個無奈之舉。事實上,宏定義的作用域早就被人诟病,特別放在頭文件中,被數次包含之後,在不經意間又被覆蓋,然後又被重新使用,也許此時已經不是原來的意思了,而我們在使用時還不知道。
為此,有一個簡單的原則可以減少宏定義的沖突,那就是盡量不要將宏定義置於頭文件當中,除非有一個非將其置於頭文件不可的理由。除此之外,還有一個策略 是,如果一個文件/庫的某個函數不會被其他地方所使用,那麼就不要將其置於頭文件當中。頭文件應該是接口,而不是麻辣燙那樣的大雜燴。
1.2枚舉類型的作用域就是枚舉變量的作用域,這個可控性更高。
二、設計目的
宏定義在編譯階段之間就已經展開,多半是為了完成“代碼縮減”(某些時候有點像函數)或者“程序的易於維護性能”(某些時候有點像全局變量)。
而枚舉類型是為了實現限制輸入。 另外,注意枚舉成員只能是整形變量。