C99 標準の変換フェーズのこのコピー アンド ペーストの説明で説明されているように、コメントの削除 (単一の空白に置き換えられます) は変換フェーズ 3 で発生し、前処理ディレクティブは処理され、マクロはフェーズ 4 で展開されます。
C90 標準 (私はハード コピーしか持っていないので、コピー アンド ペーストはありません) では、これらの 2 つのフェーズは同じ順序で発生しますが、変換フェーズの説明は、C99 標準とはいくつかの詳細でわずかに異なります。前処理ディレクティブが処理され、マクロが展開される前に、コメントが削除され、単一の空白文字に置き換えられます。
繰り返しますが、C++ 標準では、これら 2 つのフェーズが同じ順序で発生します。
' //
' コメントの処理方法に関して、C99 標準では次のように規定されています (6.4.9/2)。
文字定数、文字列リテラル、またはコメント内を除いて、文字は // 次の改行文字までのすべてのマルチバイト文字を含むコメントを導入しますが、次の改行文字は含みません。
そして、C++ 標準は (2.7) と言っています:
文字 // はコメントを開始し、次の改行文字で終了します。
したがって、最初の例は明らかにその翻訳者のエラーです-マクロが展開されたときに ' ;
' の後の文字をfoo(a)
保持する必要がありますfoo()
-コメント文字はマクロの「コンテンツ」の一部であってはなりませんthe foo()
。
しかし、バグのあるトランスレーターに直面しているため、マクロ定義を次のように変更することをお勧めします。
#define foo(x) /* junk */
バグを回避します。
ただし(そして、ここでトピックからずれています...)、コメントが処理される前に行のスプライシング(改行の直前のバックスラッシュ)が発生するため、次のような厄介なコードに遭遇する可能性があります。
#define evil( x) printf( "hello "); // hi there, \
printf( "%s\n", x); // you!
int main( int argc, char** argv)
{
evil( "bastard");
return 0;
}
これは、誰が書いたとしても驚くかもしれません。
または、ボックス スタイルのコメントが好きな人 (もちろん私ではありません!) によって書かれた次のコードを試してください。
int main( int argc, char** argv)
{
//----------------/
printf( "hello "); // Hey, what the??/
printf( "%s\n", "you"); // heck?? /
//----------------/
return 0;
}
コンパイラがデフォルトでトライグラフを処理するかどうかに応じて(コンパイラは想定されていますが、トリグラフはそれらに遭遇するほぼすべての人を驚かせるため、一部のコンパイラはデフォルトでそれらをオフにすることを決定します)、必要な動作が得られる場合と得られない場合があります。もちろん、それがどんな振る舞いであっても。