2014-10-09 76 views
3

情況1)嵌套##操作者在C預處理

#define CONCATENATE(x,y) x##y 

CONCATENATE(一個,CONCATENATE(B,C))給出aCONCATENATE(B,C)。

情況2)

#define CONCATENATE(x,y) x##y 
#define CONCATENATE2(x,y) CONCATENATE(x,y) 

CONCATENATE2(一個,CONCATENATE2(B,C))給出ABC。

爲什麼case 1不起作用?和案例2呢?
請通過一步一步的程序解釋。

+0

你的意思是第二個用例是:'CONCATENATE2(a,CONCATENATE2(b,c))'? – 2014-10-09 17:25:01

+0

@RSahu是的,我做了,我相應地編輯了這個問題。感謝提醒。 – chanzerre 2014-10-09 17:32:27

回答

2

GCC的文檔解釋這種方式:

宏參數是完全宏擴展它們是 代入宏體,之前,除非它們被字符串化或與其它代幣粘貼 。

(強調)

的##的操作數(標記粘貼)運算符,在另一方面,不宏擴展被粘貼在一起之前。因此,鑑於

CONCATENATE(a,CONCATENATE(b,c)) 

預處理程序擴展外宏的身體,因爲它是##的操作之前不會擴大CONCATENATE(b,c)。預處理器重新掃描更多的宏擴大之前,而不是執行標記粘貼,所以

a ## CONCATENATE(b,c) 

重新掃描之前成爲

aCONCATENATE(b,c) 

,並沒有宏觀aCONCATENATE(但如果有,那麼將被擴大)。

在另一方面,與

CONCATENATE2(a,CONCATENATE2(b,c)), 

參數CONCATENATE2(b,c)不是##(或#)運算符的操作數,因此它被代入宏體內,最終產生

前擴大
CONCATENATE(a, bc) 

作爲外部宏的第一個擴展。這是重新進一步擴展,產生

abc 
2

當以自引用的方式(或循環)使用宏時,就像CONCATENATE一樣,它們不會遞歸展開。這就是爲什麼:

CONCATENATE(a,CONCATENATE(b,c))給出aCONCATENATE(b,c)

在第二種情況下,CONCATENATE2的擴展在CONCATENATE處理後執行。因此,你得到正確的輸出。

宏的自引用用法在大多數情況下工作正常。例外是令牌粘貼和字符串化。

例如,如果您有:

#define #define foo(x) int x 

然後,

foo(foo(x)); 

擴展爲:

int int x; 

如果您有:

#define STR(y) #y 

然後,

STR(STR(abcd)); 

擴展爲:

"STR(abcd)"; 

更多細節:

https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html

https://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification

How does the C preprocessor handle circular dependencies?

+0

問題不在於關於字符串化,而是關於令牌粘貼。 – 2014-10-09 17:37:39

+0

@JohnBollinger,字符串化只是使用兩層宏來實現正確的宏擴展和令牌粘貼的一個例子。 – 2014-10-09 17:39:11

+0

好的,但答案卻錯了:自引用宏是指宏定義出現在它的*定義*中,而不是它的參數。它可以通過參數進行遞歸,因爲可以很容易地進行測試。 – 2014-10-09 17:49:17