代碼片段:
#define TR(m,n,p) m##n##p
int main() {
printf("%s\n", TR("abc","xy","yz"));
return 0;
}
在 GCC 下編譯報錯:pasting "abc" and "xy" does not give a valid preprocessing token。
##(Token Pasting)運算子要求運算結果必須為合法的前置處理器 Token(識別字、常數、運算子等)。字串常數 "abc" 經連接後變成 "abcxy",但 "abc" "xy" 在前置處理階段是兩個獨立字串常數 Token,而非單一 Token,故違反規範。
#define TR_IMPL(m,n,p) m##n##p
#define TR(m,n,p) TR_IMPL(m,n,p)
#define A abc
#define B xy
#define C yz
int main() {
printf("%s\n", TR(A,B,C)); // 展開為 abcxyz -> 單一識別字
return 0;
}
關鍵:先定義不帶引號的識別字巨集(A, B, C),再透過雙層宏強制參數完整展開後才進行 ## 連接,結果 abcxyz 為合法識別字。
#define DECLARE_VAR(prefix, num) int prefix##num = 0;
DECLARE_VAR(val, 1) // 展開為 int val1 = 0;
DECLARE_VAR(val, 2) // 展開為 int val2 = 0;
詳細解析請見:C 前置處理器 ## 連接符深度解析與雙層宏技巧