理解C++ 巨集

Andy Niu發表於2014-01-02

1、什麼是巨集,它解決什麼問題?

  巨集的本質是文字替換,考慮下面的需求,程式中多次使用圓周率Pi,在每個地方都使用3.1415,顯然很愚蠢。有沒有好的辦法呢?使用巨集,如下:

  #define Pi 3.1415

  這樣,編譯器在程式中遇到Pi,就使用3.1415來進行文字替換。

2、特殊字元

  考慮下面的需求,程式中多處使用文字字串。我們知道文字字串前後都要加上雙引號,我很討厭輸入雙引號。有沒有好的辦法呢?根據常識,使用下面的巨集:

  #define Str(x) "x"

  String s = Str(Hello); 期望預編譯為:String s = "Hello",其實這是有問題的?仔細分析一下,巨集的本質是文字替換。從編譯器的角度思考,哪些地方應該換,哪些地方不應該換,並不是說遇到x就替換。也就是說,對於"x",編譯器認為"x"是一個整體,其中的x不是Str(x)的x。因此,String s = "x"。那麼如何解決這個問題呢?

  與此類似,相同道理的情況是轉義字元。因此,這裡也使用特殊字元。對巨集變數前後加上雙引號的特殊字元是:#。另外還有:

  #:巨集變數前後加上雙引號

  #@:巨集變數前後加上單引號

  ##:進行拼接。

3、常用的巨集

   __LINE__           巨集在預編譯時會替換成當前的行數
   __FUNCTION__      巨集在預編譯時會替換成當前的函式名稱
   __FILE__           巨集在預編譯時會替換成當前的檔名
   __DATE__          編譯的日期(格式"Mmm dd yyyy")
   __TIME__            編譯的時間(格式"hh:mm:ss")
   __TIMESTAMP__    修改日期和時間,表示為以 Ddd Mmm Date hh:mm:ss yyyy 
   __STDC__             如果編譯器接受標準C,那麼值為1
   __VA_ARGS__          是一個可變引數的巨集  

  其他見:http://msdn.microsoft.com/zh-cn/library/windowsphone/develop/b0084kay.aspx

4、儘量少使用巨集,而應該使用替代方法。但是有些地方,還是必須要使用巨集。比如:

  (#ifndef #define #endif)以及__LINE__等,為什麼__LINE__也必須要使用巨集?

  思考:使用巨集,在當前位置進行文字替換,列印出來就是當前行數。如果使用方法,那麼列印出來的就是方法中一行內容的行數。

相關文章