2010-08-01 68 views
1

我蒸餾我的問題到這個代碼片斷 - 但它是一個更大的計劃的一部分,所以我不希望用不同的方式來做到這一點 - 我需要一種方法來使工作!奇怪的C++預處理器宏語法

當我生成這個代碼預處理後的文件:

#define OUTER(a, b) \ 
    a##b 
#define INNER(c, d) \ 
    c##d 

enum foo { 
    OUTER(INNER(x, y), z) 
}; // line 108 

int APIENTRY _tWinMain(...) 
{ 
    foo bar = xyz; // line 112 
} 

我得到:

enum foo { 
    xyz 
}; // line 108 

int __stdcall wWinMain(...) 
{ 
    foo bar = xyz; // line 112 
} 

這就是我想要的。但是,如果我嘗試編譯的代碼我得到:

錯誤C2146:語法錯誤:缺少「}」之前標識符「Z」線108
錯誤C2143:語法錯誤:缺少「;」之前 '}' 線108
錯誤C2143:語法錯誤:缺少 ';'之前 '}' 線108
錯誤C2059:語法錯誤: '}' 線108
錯誤C2065:XYZ':未聲明的標識符線112

我不能工作了!這個問題似乎由該##造成的:

#define OUTER(a, b) \ 
    a##b 

但爲什麼(以及如何解決它)是超越我...

+0

@Jack你能解釋什麼是## b的該怎麼辦?以前從未見過這個。 – InsertNickHere 2010-08-01 17:45:46

+1

@Insert它是一個預處理運算符,它將兩個參數逐字連接起來。例如,OP代碼片段中的'OUTER(test,string)'被預處理器的'teststring'替換。 – 2010-08-01 17:47:21

+0

好吧,我可以證實,這也發生在gcc中,他們的錯誤更具描述性。就是說它不能粘貼''''和'z'。它看起來像預處理器不能這樣做嵌套粘貼,但這是猜測在這一點上。希望有點幫助.. – Blindy 2010-08-01 17:48:31

回答

9

使用這個代替:

#define CONCAT(X,Y) X##Y 
#define OUTER(a, b) CONCAT(a,b) 
#define INNER(a, b) CONCAT(a,b) 

enum foo { 
    OUTER(INNER(x, y),z) 
}; // line 108 

int main(...) 
{ 
    foo bar = xyz; // line 112 
} 
+0

嗚呼它的作品!但你能向我解釋爲什麼它有效嗎?爲什麼我的預處理輸出正確​​?我從下面描述的gcc錯誤中看到它似乎保留了「)」並嘗試將「z」連接到「xy」「?但是這不會出現在我的預處理輸出中! – Jack 2010-08-01 17:59:29

+0

閱讀喬納森·萊弗勒的規範答案: HTTP://計算器。com/questions/1489932/c-preprocessor-and-concatenation – 2010-08-01 18:04:54

+0

啊!正如我想的那樣,OUTER是否獲得「INNER(c,d),z」而不是「xy,z」?這是有道理的。但我仍然不明白爲什麼我的預處理輸出是正確的! – Jack 2010-08-01 18:05:11

1

如果你正在使用gcc,那麼你可以給它-E選項來查看預處理輸出。然後,您可以輕鬆看到預處理器輸出的內容以及如何進一步調試宏。其他編譯器也有類似的選擇。

2

預處理你的榜樣與gcc結果:

enum foo { 
t.c:7:1: error: pasting ")" and "z" does not give a valid preprocessing token 
    xy z 
}; 

這應該給你的,爲什麼路德的解決方案工作的線索,你沒有。