2011-07-19 17 views
8

預期這不起作用:宏擴展的確切步驟是什麼?

#define stringify(x) #x 
printf("Error at line " stringify(__LINE__)); 

這工作:

#define stringify1(x) #x 
#define stringify(x) stringify1(x) 
printf("Error at line " stringify(__LINE__)); 

那是什麼預處理用來擴大這些宏的優先級?

+0

請參閱[GCC C預處理器文檔](http://gcc.gnu.org/onlinedocs/cpp/)。您將特別對[字符串化]部分感興趣(http://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification)。 – ughoavgfhw

+0

[#define STR(x)#x「和」#define STR(x)VAL(x)「與宏」#define VAL(x)#x「之間的區別是什麼?](http: //stackoverflow.com/questions/8283596/whats-the-difference-between-the-macros-define-strx-x-and-define-strx) –

回答

13

當擴展宏,預處理器擴展宏的參數僅當這些參數不經受字符串化(#)或標記粘貼(##)運營商。所以,如果你有這樣的:

#define stringify(x) #x 
stringify(__LINE__) 

然後,預處理程序所做的擴大__LINE__,因爲它是字符串化操作的參數。但是,當你這樣做:

#define stringify1(x) #x 
#define stringify(x) stringify1(x) 
stringify(__LINE__) 

然後,擴大stringify時,預處理器擴展__LINE__當前的行號,因爲x不與的stringify定義無論是字符串化或標記粘貼的操作者使用。然後它擴大stringify1,我們得到我們想要的。

C99標準的相關語言來自§6.10.3.1/ 1:

參數的函數宏的調用後已經確定,參數替換髮生。替換列表中的參數除非在前面加上###預處理令牌或後跟##預處理令牌(見下文),否則在擴展包含在其中的所有宏之後,替換爲相應的參數。在被替換之前,每個參數的預處理標記完全被宏代替,就好像它們構成了預處理文件的其餘部分一樣;沒有其他預處理令牌可用。

條款§6.10.3.2和6.10.3.3去分別定義###運營商的行爲。

+0

特別處理'#'和'##'的理由是什麼? –