5

次のプログラムを順守してください。

#include __FILE__
main(){}

プリプロセッサは、それ自体の内部のコピーを含む無限の再帰でスタックし、main()すでに定義されていることについて不平を言います。


マクロを使用してファイルを含めることができる場合、それに基づいてファイル名を派生させて含めることはできます__FILE__か?


"foo.h"たとえば、中に含めたいのです"foo.cpp"が、から派生してい__FILE__ます。

  • ##マクロを連結します。
  • マクロ を文字列化することも可能です。

プリプロセッサで実行できますか?

4

2 に答える 2

6

C規格では、次の3つの形式が指定されています#include

#include <file>
#include "file"
#include ANYTHING ELSE

前の2つのケースでは、マクロ展開が行われないため、動作を変更する方法はありません。3番目のケースでは、C99は次のように述べています(§6.10.2p4):

ディレクティブの後の前処理トークン#includeは[マクロ拡張]です。すべての置換の後に生じるディレクティブは、前の2つの形式のいずれかに一致する必要があります[脚注:隣接する文字列リテラルは単一の文字列リテラルに連結されないことに注意してください]。<と>の前処理トークンのペアまたは"文字のペアの間の一連の前処理トークンを組み合わせて単一のヘッダー名の前処理トークンにする方法は、実装によって定義されます。

わずかに異なりますが、事実上同等の表現がC++98§16.2p4に表示されます。

「shall」を含む文には厳しい要件があります。この場合、プログラムは、で始まり、で終わるトークンのシーケンス、またはで始まり、で終わるANYTHING ELSEトークンのシーケンス以外に展開されると、形式が正しくありません。トークンのそのシーケンスの正確な解釈は実装で定義されていますが、脚注は文字列リテラルの連結を明確に禁止していることに注意してください。<>"

したがって、の展開__FILE__は文字列定数であるため、でそれを使用する唯一の方法は次の#includeとおりです。

#include __FILE__

あなたが発見したように、これは無限の再帰につながり、そして

#define LT <
#define GT >
#include LT __FILE__ etc GT

これは、私が便利にテストできるすべてのコンパイラに面白いが役に立たない効果をもたらします。上記が次の名前のファイルにあると仮定しますtest.c

  • "test.c" etcGCCは、引用符とスペースを逐語的に含めて、という名前のファイルを開こうとします。
  • clangはさらにリテラルであり、同じファイル名を検索しますが、先頭と末尾にスペースがあります。
  • MSVCマクロ- (これは適合違反であると私は考えています)のみを展開し、一致するものがないと文句を言ってからという名前のファイルを開こうとします。LT>__FILE__ etc GT

GCCの振る舞いはここに文書化されています;あなたは他のことについてあなた自身でいます。)

tl; dr:プリプロセッサの内部からやりたいことをする方法はありません。ビルドシステムから含めるファイルの名前を調べて、-Dスイッチでコンパイラに通知することをお勧めします(Unixyシステムでは、二重引用符が必要です。CMD-DINCLUDEME='"includeme.h"'は話せません)。

于 2012-11-21T02:18:59.743 に答える
0

The best I've come up with is this:

#define foo(x) #x
#include foo(x)

prog.cpp:2:16: error: x: No such file or directory

于 2012-11-21T02:07:09.737 に答える