は、Cプリプロセッサストリップコメントや拡大のマクロです。[重複]

StackOverflow https://stackoverflow.com/questions/1510869

質問

この質問に答えはこちら

このことを考え(ひどいもので、ものすごい、いい、悪いコードの構造:

#define foo(x) // commented out debugging code

// Misformatted to not obscure the point
if (a)
foo(a);
bar(a);

私は見た二つのコンパイラでコンパイル'preprocessorsの発生異なる結果このコード:

if (a)
bar(a);

if (a)
;
bar(a);

これは悪いことのためのポータブルドラインをサポートしています。

私の質問:何を更新することになっているのです、と。Elideコメント、または拡大のマクロです。

役に立ちましたか?

解決

残念ながら、オリジナル ANSI C仕様 を除きプリプロセッサの特徴第4条("この仕様はC言語です。で提供されており、図書館やプリプロセッサー.").

C99仕様 取り扱うこexplicityれています。また、コメント交換シングルスペースの翻訳の位相"は、が起こる前の前処理指令の構文解析.セ6.10ます。

VC++GNU Cコンパイラ 両このパラダイム-その他のコンパイラが対応だけでなく、古いものだC99の対応になるので、安心です。

他のヒント

で説明したように前処理ディレクティブが処理され、マクロは位相4で展開している間(それらが単一の空白で置き換えられている)コメントを除去C99規格の翻訳フェーズのこのコピー-N-貼り付けdecription には、翻訳段階3で起こります。

翻訳段階の記述はC99標準からいくつかの詳細が若干異なるものの、

(私はハードコピーを持っているので、無コピー-N-ペースト)C90標準では、これら二つの相は、同じ順序で起こります - 。コメントは削除され、ディレクティブを前処理する前に、単一の空白文字に置き換え処理され、マクロが展開されているという事実は変わりません。

この場合も、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;
}

トリグラフに処理するかどうか、あなたのコンパイラのデフォルト設定に応じて、(コンパイラ)になっていますが、トリグラフは驚きほぼそれら横切る誰もが、いくつかのコンパイラが決めるので、それらをデフォルトでオフにするには、あなたかもしれないまたはあなたが望む行動取得できない場合があります - 。どんな行動もちろん、です。

MSDN のによると、コメントが交換されますトークン化段階における単一のスペースと、 これはマクロが展開される前の段階の前に起こっています。

あなたのマクロで//コメントを置いてはいけません。あなたがコメントを入れなければならない場合は、/ * * /を使用します。また、あなたはあなたのマクロでのミスがあります:

#define foo(x) do { } while(0) /* junk */

この方法では、fooが常に使用しても安全です。たとえばます:

if (some condition)
    foo(x);

にかかわらず、fooは、いくつかの式に定義されているかどうかのコンパイラエラーをスローすることはありません。

#ifdef _TEST_
#define _cerr cerr
#else
#define _cerr / ## / cerr
#endif
  • 事業一部のコンパイラでコンパイル(VC++版).時 _TEST_ は未定義ですが、

    _cerr...

    取って替わられる日がくるとのコメントライン

    //cerr...

感覚が求められるコンプライアンス三つのステップ

  1. ストリップ
  2. 拡大マクロ
  3. ストリップを再度

このコンパイラです。私はファイル。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top