巨集定義和列舉型別的區別
摘要:在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列舉型別的作用域就是列舉變數的作用域,這個可控性更高。
二、設計目的
巨集定義在編譯階段之間就已經展開,多半是為了完成“程式碼縮減”(某些時候有點像函式)或者“程式的易於維護效能”(某些時候有點像全域性變數)。
而列舉型別是為了實現限制輸入。 另外,注意列舉成員只能是整形變數。
相關文章
- define巨集定義和const常量定義之間的區別
- c 語言中巨集定義和定義全域性變數的區別變數
- #define巨集與列舉以及typedef關鍵字的區別
- 列舉型別型別
- Java列舉型別的使用和原理Java型別
- 10-列舉型別和流型別
- ENUM列舉型別型別
- java列舉型別Java型別
- java 列舉型別Java型別
- java中的列舉型別Java型別
- JPA不識別MySQL的列舉型別MySql型別
- 介面和列舉在方法中的區別
- Java - Enum 列舉型別Java型別
- Python 中的列舉型別Python型別
- 窺探Swift之別樣的列舉型別Swift型別
- JavaSE基礎:列舉型別Java型別
- mysql之ENUM列舉型別MySql型別
- 【C++】資料型別-列舉型C++資料型別
- 一個C++巨集定義與列舉定義重複的編譯錯誤C++編譯
- java中的列舉型別學習Java型別
- 列舉型別在JPA中的使用型別
- C#中列舉型別的使用C#型別
- 關於mysql中欄位定義的型別int、tinyint區別MySql型別
- C++ 列舉型別介紹C++型別
- 列舉型別分享 第五節型別
- java基礎(十一) 列舉型別Java型別
- 列舉型別與位運算型別
- 關於C++列舉型別C++型別
- Typescript 下 Mongoose 外來鍵型別&外來鍵陣列型別定義&型別保護&聯合型別理解TypeScriptGo型別陣列
- PHP 列舉型別的管理與設計PHP型別
- c#中值型別和引用型別的區別C#型別
- 【四】使用列舉和結構來建立值型別型別
- [C++]結構體、共同體和列舉型別C++結構體型別
- DTD文件型別定義型別
- js基本型別和引用型別區別JS型別
- COM、COM+和DCOM的定義和區別
- Java基礎教程(15)–列舉型別Java型別
- C語言 列舉資料型別C語言資料型別