2016-12-25 14 views
2

は、次のコードを考えてみましょう。この場合なぜCプリプロセッサはスキップしたブロック内の無効なディレクティブを無視しないのですか?

#if 0 
    #foobar 
#endif 

を、プリプロセッサは、#foobarが有効なプリプロセッサディレクティブではないことを文句はありません。 #if 0のためにブロックをスキップするだけで、コードは正常にコンパイルされます。

今すぐ次のコードを考えてみます。

#if 0 
    #if 1 
#endif 

この場合は、プリプロセッサが突然行方不明#endifディレクティブがあることを訴えます。 #if 0の場合であっても、プリプロセッサは#if 0ブロックにあるものを完全に無視しているようには見えないので、混乱しています。 #ifディレクティブが解析されているようで、プリプロセッサはその正確さを強制します。つまり、スキップされたブロックでも#endifで一致する必要があります。

以前、私は#if 0/#endif使用してブロックをカプセル化すること/**/を使用して、それをコメントに相当したという印象でした。しかし、それは明らかにそうではありません。したがって

私の質問:

  1. この設計の論理的根拠は何ですか?プリプロセッサは、#if 0のような特定のディレクティブを使用してスキップするようにプリプロセッサに明示的に指示されているブロックであっても、#ifディレクティブを正しく一致させるのはなぜですか?

  2. 正確にのディレクティブは、#if 0ブロックで処理されますか。上記の例に示すように、プリプロセッサは無効なプリプロセッサディレクティブ(#foobar)には言及しませんが、不一致の#ifディレクティブについては不平を言います。したがって、どのプリプロセッサディレクティブが実際に#if 0ブロックで処理されますか? #if/#ifdef/#elif/#else/#endifのみ、または#if 0ブロックで処理されるディレクティブがさらにありますか?

+4

プリプロセッサは* which * '#if'に' #endif'がありません。インデントはそれを伝えません! 2番目の例では、 '#endif'をインデントするとエラーメッセージが表示されますか? –

+3

プリプロセッサ*は、取られていないブランチの内部でも '#if' /' #endif'指示文を見る*を持っています。そうしないと、 '#if'はおそらく動作しません。 –

+1

D'oh、そうです、もちろん意味があります。なぜそれがそうでなければならないのかは非常に明白です。さて、私はクリスマスにそれを非難してみましょう:) – Andreas

答えて

7

制御フローを変更する可能性のあるディレクティブのみが処理されます。残りは#foobarのように無視されます。

(:ISO/IEC 9899:から引用201X 6.10.1条件付き包含6)


各指令の状態が順番にチェックされます。 false(ゼロ)と評価された場合、制御するグループ はスキップされます。ディレクティブは、ネストされた条件のレベルを追跡するためにディレクティブ を決定する名前によってのみ処理されます。 ディレクティブの前処理トークンの残りは無視されます。 グループ内の他の前処理トークンと同じです。

関連する問題