web-dev-qa-db-ja.com

#defineマクロで#記号をエスケープしますか?

詳細な説明は省きますが、#defineに展開される#includeマクロを使用したいと思いますが、 '#'記号はプリプロセッサを混乱させます(引数を引用したいと考えているため)。

たとえば、私はこのようなことをしたいです:

#define MACRO(name) #include "name##foo"

そしてそれをこのように使用します:

MACRO(Test)

次のように展開されます:

#include "Testfoo"

控えめな#記号は、プリプロセッサがbarfする原因となっています。 MinGWは私に次のエラーを与えます:

'#' is not followed by a macro parameter

#記号をエスケープする必要があると思いますが、これが可能である場合もそうではありません。

はい、マクロは確かに悪です...

39
Rob

私が覚えている限り、defineで別のプリプロセッサディレクティブを使用することはできません。

30
EFraim

isハッシュトークンを前処理済みのトークンストリームに挿入することができます。次のようにして行うことができます。

#define MACRO(hash, name) hash include name
MACRO(#,"hello")

-展開して:

# include "hello"

ただし、標準では、前処理ディレクティブの存在について、このような行のさらなる分析を明示的に除外しています[cpp.rescan]:

結果として完全にマクロで置き換えられた前処理トークンシーケンスは、類似している場合でも、前処理ディレクティブとして処理されません。

34
ybungalobill

問題は、プリプロセッサの出力に実際に#記号が含まれていないことです。

どうやら、プリプロセッサがファイルを再解析して、マクロ展開の一部として新しく作成された#includeディレクティブを処理するようにしたいようです。そのようには機能しません。行が#で始まる場合、それはプリプロセッサの命令であり、解釈されます。行が#で始まらない場合、それはマクロ置換を含むプリプロセッサ変換のみを受けます。これは1行に1回のテストです。

MACRO(Test)

#で始まりません。したがって、プリプロセッサディレクティブとして解釈されません。代わりに、マクロ置換ルールが適用されます。

28
MSalters

これは、マクロで#を使用すると特別な意味があるためです。

#  means quote the following token (which should be a macro parameter name)
## means concatenate the preceding and following tokens.

あなたの状況では、#の後に適切なトークンが続きません。したがって、あなたの状況では、間接的なレベルを通過する必要があります。

#define     QUOTE(name)     #name
#define     TEST(name)      QUOTE(name ## foo)

#include TEST(scot)
11
Martin York

それはできません。プリプロセッサディレクティブは、マクロ展開の前に認識されます。マクロがプリプロセッサディレクティブのように展開されると、そのディレクティブは認識されません。あなたができる最善のことは、ファイル名のマクロを作成することです:

#define MACRO(name) "name##foo"
...
#include MACRO(Test)
6
John Bode

これmight機能(通常の#defineパラメータなしのマクロですが、パラメータ付きのマクロではテストしていません)。

#define MACRO(name) <name##foo>
#include MACRO(Test)
2
Sam Harwell
#define PARAM_NAME Param
#define GETNAME_(a) #a
#define GETNAME(a) GETNAME_(a)

int Param;
printf("%s = %i\n", GETNAME(PARAM_NAME), PARAM_NAME);
1
user6858363
#define HASH_SIGN #
BOOST_PP_CAT(HASH_SIGN, include)
1
David F.