2011-01-27 10 views
12

C/C++を扱ってくれた人の多くは、プリプロセッサの動作の仕組みが多少異なると思います。私は今日までそう思っていたが、私の直感は間違っていた。話はここにあります:(奇妙な?)GCCプリプロセッサの振る舞い

今日私は何かを試みましたが、結果を説明することはできません。何が起こる

#define A B 
#define B A 

A 
B 

: 最初に以下のコードを考えてみ?まあ、-Eフラグとそれをコンパイルした後の結果はこれです:

まあ
A 
B 

、[OK]を、多分誰もが期待していないものを、それが説明可能です。私はプリプロセッサが何らかの問題があると考えて、何もしなかったと思います。 、私のために、説明のつかない結果を今すぐ

#define A B 
#define B A C 
#define C x 

A 
B 

A x 
B x 

はどのようにこれが起こった私が試した

次のことは、このでしたか?私はこれがどうして起こったのか合理的な方法を理解することはできません。最初のコマンド(#define A B)は実行できません。なぜなら、AはBに置き換えられ、最終結果は両方で同じになるからです。しかし、そうでなければ、 "A x"が起こる方法はありません!

私の質問:何が欠けていますか?明らかに、私はプリプロセッサの仕組みの正確な方法を知らない。あなたはそれについての情報源を知っていますか?

+0

との#defineを回避する必要が理由です... – Goz

+0

うん、これは私がすべてでそれらを使用しないことを意味するものではありませ...もう一つの理由です。いくつかのタスクでは、非常に便利です(i.m.oに行く方法)。 – George

答えて

13

Self-Referential Macrosが説明しています。拡張は深く適用されますが、マクロが参照すると停止します。

+0

ニースと役立つリンク、ありがとう! – George

5
#define A B 
#define B A C 
#define C x 

A -> B -> A C -> A x 
B -> A C -> B x 

拡張トークンによってトークン "レイジー"

3

まあで、[OK]を、多分誰もが 期待するが、それは説明できるではないでしょう。私は プリプロセッサはどういうわけか何らかの問題があり、 を と考えて、 しなかったと思います。

いいえ。プリプロセッサが展開を行う場合、シンボルは1回だけ展開されます。だからあなたの最初の例では、A:AはBに、BはAに展開され、ここで展開が停止します。第2行目では、BはAに展開され、Bはすでに展開されているため、展開が停止するBに展開されます。

ロジックを2番目の例に適用すると、結果がすぐに明らかになります。

5

置換の各チェーンは、たいていのマクロ定義を1回しか訪問することができません。とりわけ、これは再帰マクロを持つことができないことを意味します。あなたの第二の例について

置換は次のようになります。

A --[evaluate A]--> B --[evaluate B]--> A C --[evaluate C]--> A x 
B --[evaluate B]--> A C --[evaluate A,C]--> B x 

最初の行の最後のステップの間、それはすでに以前に呼び出されたので、Aは評価されません。同様に、2行目では、評価は最初の手順ですでに訪れているので、Bで終了します。

C99規格の該当するセクションは、6.10.3.4再スキャンおよび更なる交換です。

+0

説明をありがとう!私は文法と言語の文脈の中で考えていました。私はその明らかな説明を完全に逃しました。 – George