2013-10-29 23 views
14

我發現an interesting little blog post,說明如何通過使用行號以產生一個宏(半)唯一的名字:爲什麼這個級聯宏需要一個間接級別?

// Do magic! Creates a unique name using the line number 
#define LINE_NAME(prefix) JOIN(prefix, __LINE__) 
#define JOIN(symbol1, symbol2) _DO_JOIN(symbol1, symbol2) 
#define _DO_JOIN(symbol1, symbol2) symbol1##symbol2 

這裏有兩件事情,真的讓我困惑:

  1. 爲什麼會出現LINE_NAME如果在文件中聲明JOIN後宏甚至可以工作?我認爲C預處理器做了一個線性傳遞,因此需要根據依賴性來定義宏,就像C函數在使用之前需要定義一樣。
  2. 爲什麼需要同時使用JOIN_DO_JOIN宏才能獲得正確的結果?在宏中具有這種間接級別似乎很奇怪。

我有一種感覺,這兩個問題的答案都是相關的,並且與C預處理器評估宏的方式有關。 (然而,我對宏如何工作的直覺很明顯,因爲我甚至都沒有想到這個例子是有效的。)

+0

可能重複[爲什麼我需要宏的雙層間接?](http://stackoverflow.com/questions/8231966/why-do-i-need-double-layer-of-indirection-for -macros) – Antonio

回答

8

爲什麼如果在文件中聲明JOIN後,LINE_NAME宏甚至可以工作?

宏不是函數,當你調用它們時,編譯器將它們展開,並且在那裏的編譯器知道所有已定義的宏。

爲什麼有必要同時使用JOIN和_DO_JOIN宏來獲得正確的結果?在宏中具有這種間接級別似乎很奇怪。

因爲__LINE__本身就是一個宏,它需要兩級擴展。

否則輸出不是prefix1234它將是prefix__LINE__

閱讀this answer也非常有用,並this thread

+0

好的,所以額外的宏本質上只是強制預處理器對結果字符串進行另一次查找/替換。如果'JOIN(prefix,__LINE __)'的結果也恰好與宏名稱匹配,那麼它是否也會被替換? – DaoWen

+1

@DaoWen:是的。確切的規則是:如果你有一個宏定義'#define FOO(x,...)...',那麼任何參數'x'都會遞歸地擴展*除非它是字符串化或標記粘貼操作符的參數*('#'和'##')。見C99§6.10.3.1/ 1。 –

相關問題