web-dev-qa-db-ja.com

正確には、二重ストリング化のトリックはどのように機能しますか?

少なくとも一部の[〜#〜] c [〜#〜]プリプロセッサを使用すると、名前ではなくマクロの値を、ある関数のようなマクロから、それを文字列化する別のマクロへ:

#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */

使用例 ここ

これは、少なくともGCCとClang(両方で-std=c99)ですが、よくわかりませんhow C標準の用語で機能します。

この動作はC99によって保証されていますか?
その場合、C99はそれをどのように保証しますか?
そうでない場合、どの時点で動作はC定義からGCC定義に移行しますか?

81
Peter Hosey

はい、保証されています。

これは、マクロへの引数自体がマクロ展開されているため機能しますexceptここで、マクロ引数名は、文字列#またはトークンペースト##を使用してマクロ本体に表示されます。

6.10.3.1/1:

...関数のようなマクロの呼び出しの引数が識別された後、引数の置換が行われます。置換リストのパラメーターは、前に#または##前処理トークンが続くか、##前処理トークンが後に続く場合(下記参照)を除き、そこに含まれるすべてのマクロが展開された後、対応する引数に置き換えられます...

したがって、STR1(THE_ANSWER)を実行すると、STR1の引数がマクロ展開されていないため、「THE_ANSWER」が得られます。ただし、STR2の定義に代入されると、STR2 isマクロ展開された引数なので、STR1に42の引数が与えられ、結果は "42"になります。

77
Steve Jessop

スティーブが指摘するように、これは保証されており、C89標準以来保証されています-これは、再帰的にマクロと委任でおよび##演算子を成文化した標準でした本体が引数にまたは##を適用しない場合にのみ、本体に代入する前にargs内のマクロを展開します。この点で、C99はC89から変更されていません。

20
Chris Dodd