87

少なくとも一部のCプリプロセッサでは、マクロの名前ではなく値を文字列化できます。これは、ある関数のようなマクロを介してマクロを文字列化する別のマクロに渡すことによります。

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

使用例はこちら

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

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

4

2 に答える 2

81

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

これは、マクロの引数名が文字列化子 # またはトークン貼り付け記号 ## を使用してマクロ本体に表示される場合を除いて、マクロへの引数自体がマクロ展開されるため機能します。

6.10.3.1/1:

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

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

于 2010-05-01T23:24:25.180 に答える
21

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

于 2010-05-01T23:47:36.793 に答える