2010-05-01 68 views
74

至少一些Ç預處理器讓你stringize宏的價值,而不是它的名稱,將其通過一個函數宏到另一stringizes它:雙串化技巧究竟如何工作?

#define STR1(x) #x 
#define STR2(x) STR1(x) 
#define THE_ANSWER 42 
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */ 

使用案例here

這並不工作,至少在GCC和鏘(均與-std=c99),但我不知道怎麼工作在C-標準的條款。

此行爲是否由C99保證?
如果是這樣,C99如何保證它?
如果不是,行爲從C定義到GCC定義的哪一點?

+1

如果你說「至少有一些」,這是否意味着你看到了一個它不工作的地方?我願意向供應商寫一份錯誤報告。 – Jens 2011-05-20 21:04:10

+0

@Jens:不;我沒有。我使用過的每個編譯器(即GCC和Clang)都會實現此行爲。 – 2011-05-21 03:10:33

回答

69

是的,它有保證。

它的工作原理,因爲參數宏本身是宏展開,除了其中宏觀參數的名字出現在宏體與stringifier#或令牌貼紙##。

6.10.3.1/1:

...的論據, 調用一個函數宏 已經確定,論證 替代發生後。在替換列表中的參數 ,除非或者前面是# ##預處理 令牌或後跟一個## 預處理記號(見下文),則 所有的宏之後,由相應的參數替換 其中所含 已經擴大...

所以,如果你這樣做STR1(THE_ANSWER)那麼你得到「THE_ANSWER」,因爲STR1的參數不是宏擴展。然而,STR2 的參數是,它被代入到STR2的定義中時被宏展開,因此STR1的參數爲42,結果爲「42」。

19

正如史蒂夫指出,這是保證的廣告,並且由於C89標準已經保證的廣告 - 這是標準的編入宏和任務前代遞歸擴展args中宏##運營商他們進入身體當且僅當身體不適用##的論點。 C99在這方面與C89保持不變。