web-dev-qa-db-ja.com

##および__LINE__を使用したCマクロの作成(位置決めマクロとのトークン連結)

行番号に基づいた名前で関数を作成するCマクロを作成したい。私は次のようなことができると思った(実際の関数は括弧内にステートメントを持っているだろう):

#define UNIQUE static void Unique_##__LINE__(void) {}

私は次のようなものに拡大したいと思っていました:

static void Unique_23(void) {}

それは機能しません。トークンの連結では、位置決めマクロは文字通り処理され、最終的に次のように展開されます。

static void Unique___LINE__(void) {}

これは可能ですか?

(はい、これがどれほど役に立たないとしても、これをやりたい本当の理由があります)。

100
DD.

問題は、マクロの置換がある場合、文字列化演算子#もトークン貼り付け演算子##も適用されない場合にのみ、プリプロセッサがマクロを再帰的に展開することです。そのため、いくつかの追加の間接層を使用する必要があります。再帰的に展開された引数でトークン貼り付け演算子を使用できます。

#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define UNIQUE static void TOKENPASTE2(Unique_, __LINE__)(void) {}

その後、__LINE__UNIQUEの展開中に行番号に展開され(#または##のいずれにも関係しないため)、その後トークンの貼り付けが行われますTOKENPASTEの展開。

同じ行にUNIQUEマクロの複数のインスタンス化が必要な場合に、評価されるたびに新しい整数に展開される__COUNTER__マクロも存在することにも注意してください。注:__COUNTER__は、MS Visual Studio、GCC(V4.3以降)、およびClangでサポートされていますが、標準Cではありません。

165
Adam Rosenfield