巨集定義和列舉型別的區別

誰不小心的發表於2013-10-12

摘要:在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列舉型別的作用域就是列舉變數的作用域,這個可控性更高


二、設計目的


巨集定義在編譯階段之間就已經展開,多半是為了完成“程式碼縮減”(某些時候有點像函式)或者“程式的易於維護效能”(某些時候有點像全域性變數)。

而列舉型別是為了實現限制輸入。 另外,注意列舉成員只能是整形變數。

相關文章