与えられた
#define cat(x,y) x##y
呼び出しcat(a,1)
は戻りますがa1
、cat(cat(1,2),3)
未定義です。ただし、も定義する#define xcat(x,y) cat(x,y)
と、の結果xcat(xcat(1,2),3)
はになり123
ます。なぜそうなのか、詳しく説明してもらえますか?
与えられた
#define cat(x,y) x##y
呼び出しcat(a,1)
は戻りますがa1
、cat(cat(1,2),3)
未定義です。ただし、も定義する#define xcat(x,y) cat(x,y)
と、の結果xcat(xcat(1,2),3)
はになり123
ます。なぜそうなのか、詳しく説明してもらえますか?
GCC と Clang の両方を使用してこれをテストしました。
GCC は次のエラーを返します。
test.c:6:1: error: pasting ")" and "3" does not give a valid preprocessing token
Clangはエラーを出します:
test.c:6:11: error: pasting formed ')3', an invalid preprocessing token
int b = cat(cat(1,2),3);
発生しているように見えるのは、コンパイラcat(1,2)
が展開されるとすぐに結果を括弧で囲むことです。そのため、コードを呼び出すとcat(1,2)
、実際に(12)
. cat((12),3)
その後、再度呼び出すと((12)3)
、有効なトークンではない が発生し、コンパイル エラーが発生します。
一般的な意見は、「トークン貼り付け演算子 (##) を使用するときは、2 つのレベルの間接化を使用する必要がある」(つまり、xcat
回避策を使用する) ことです。マクロに二重層の間接化が必要なのはなぜですか? を参照してください。2 つのトークンを一緒に貼り付ける必要があるマクロはどうすればよいですか? .
xcat(x,y) では、x と y は ## 演算子に隣接していないため、置換される前にマクロ展開されます。
したがって、x は xcat(1,2) として識別され、y は 3 として識別されます。ただし、置換前に、x は cat(1,2) にマクロ展開され、1##2 になり、12 になります。 、xcat(xcat(1,2),3) は cat(12,3) に展開され、123 になります。
これは動作します --> cat(xcat(1,2),3) --> cat(cat(1,2),3) --> cat(12,3)
トークンの貼り付けはすべて有効なプリプロセッサ トークンになるため、動作は明確に定義されています。つまり、展開された式はどの段階でも有効なトークンである必要があります。
猫が実際に2回連続で拡張されるかどうかはわかりません。だから、なぜコンパイラはのようなメッセージを生成するのだろうかと思います'pasting ")" and "3" does not give a valid preprocessing token'
。また、内側の猫が最初に拡張されるとは思いません。したがって、出力は。になると思いますcat(1,2)3
。それは、コンパイラがこれをどのように解釈するかを理解するように私に指示します。