C++宏的作用與C#裏宏的代替(二)

繼續宏的作用,上一篇文章總結了使用宏定義常量和使用宏防止多重包含。下邊接着總結。

3、條件編譯

C語言中,預處理過程讀入源代碼,檢查包含預處理指令的語句和宏定義,並對源代碼進行相應的轉換,預處理過程還會刪除程序中的註釋和多餘的空白符號。預處理指令是以#開頭的代碼行,#必須是該行除了空白字符外的第一個字符。#後是指令關鍵字,在#和指令關鍵字之間允許存在若干空白字符。

使用宏進行條件編譯的用法與使用宏防止多重引用類似。示例如下:

#ifdef _DEBUG //如果定義了_DEBUG,則執行#ifdef _DEBUG與#else之間的指令;

cout<<"debug"<<endl;

#else //否則,執行#else與#endif之間的指令。

cout<<"release"<<endl;

#endif

使用條件編譯,方便程序員在調試程序的過程中,執行一些在程序發佈後並不需要執行的指令。只要在需要調試的代碼前加上_DEBUG的定義,就可以在調試程序的過程中輸出調試信息。這樣方便我們查看程序在運行過程中有沒有出現錯誤,定位錯誤出現的地方。而在程序發佈之前,取消_DEBUG的定義就可以不再執行調試代碼。

4、宏函數

函數的調用是需要一定的時間和空間代價的。因爲系統在調用函數時,需要保留"現場",即將程序要執行的指令的下一條指令的位置壓入棧,然後轉入調用函數去執行,調用完函數後再返回主調函數,恢復"現場",返回到棧裏保存的的下一條指令的位置繼續執行。所以函數的調用需要額外的時間和空間代價。

而宏函數則不存在上述問題,宏函數在預編譯時,同函數定義的代碼來替換函數名,將函數代碼段嵌入到當前程序,不會產生函數調用,所以會省去普通函數保留現場恢復現場的時間,但因爲要將定義的函數體嵌入到當前程序,所以不可避免的會佔用額外的存儲空間。在頻繁調用同一個宏的時候,該現象尤其明顯。

宏函數的示例定義如下:

#define MAX(a,b) ((a)<(b)?(b):(a))

宏函數的優點在於避免函數調用,提高程序效率。

同時需要注意的是inline標識符。inline也將函數定義爲內聯的。但是使用內聯函數需要注意的是:函數體必須十分簡單,不能含有循環、條件、選擇等複雜結構,否則就不能作爲內聯函數了。事實上,有時候即便你沒有將函數指定爲內聯函數,編譯器也會將一些簡單的函數作爲內聯函數處理,而對於一些複雜的函數,即使聲明爲內聯函數,編譯器也不會理會的。inline函數的瓶頸就在於此,使用inline標識符將函數聲明爲內聯的,但這只是一種提示,到底編譯器有沒有優化還依賴於編譯器的實現,而使用宏函數則完全由代碼本身控制。但在使用宏函數的時候,需要明確的是宏函數只是簡單的替換,需要注意括號的使用。

5、取消宏定義

#undef指令可以取消前面用#define定義的宏,取消後可以重新定義宏,該指令的使用並不多,因爲用的過多會使代碼維護起來比較困難。一般用於配置文件中,用來清除一些關於#define的定義,保證宏定義的唯一性。

示例:#undef _DEBUG



午飯時間,晚上繼續...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章