3

私はあまりCプログラマーではありませんが、Cマクロは、プリプロセッサがマクロ定義を取得し、マクロ名が表示される場所に配置する、検索と置換の機能のようなものであると想定していました。

これは、Dragon Bookの動的スコープルールの例と、それらがマクロにどのように適用されるかを示しています。

#define a (x + 1)

int x = 2;
void b () { int x = 1; printf("%d\n", a); }
void c () { printf("%d\n", a); }
void main () { b(); c(); }

また、動的スコープルールがxマクロ内の名前にどのように適用されるかについても説明しますaa私はそれが基本的にプログラムを置き換えてからコンパイルするだろうと仮定していたので、スコープルールはあなたが代わりに(x + 1)書いた場合とまったく同じになるでしょう(これは静的スコープルールになります)。(x + 1)a

誰かがこれを明確にすることができますか?

編集:参照されている本はコンパイラ:原則、技術、ツール第2版です。引用された例は31-32ページからのものです。

4

3 に答える 3

2

あなたの理解は正しいです:識別子のすべての使用法を見つけて、それを。aで置き換えてください。それはまさにプリプロセッサが行うことです。a(x + 1)

オブジェクトのようなマクロ(のような)に関して説明できる唯一の「スコープ」aは、マクロ自体のスコープ#defineです。マクロのスコープは、(ディレクティブを使用して)定義された行から次の行までです。未定義(#undefディレクティブ付き)、または変換単位(.cppとそれに含まれるすべてのヘッダー)の終わりまで(未定義にならない場合)。

于 2012-07-18T03:14:59.520 に答える
2

#defineの動作についてのあなたの理解は正しいです。

この本が「動的スコープ」と言っているのは、マクロが定義されている場所ではなく、マクロが呼び出されている環境に基づいて名前xが解決されるという意味だと思います。したがって、#defineの直前にグローバル変数x = 3を設定した場合、それは#defineのxの値とは無関係です-マクロを使用する場合は常にxの値を使用します-他にローカル変数がある場合マクロを使用する関数の変数xの場合、ローカル値が使用されます。

これは、名前がそのローカルの字句環境を参照する字句スコープ(C言語およびほとんどすべての現代言語で実際に使用されるもの)とは対照的です。たとえば、例の#defineを単純なステートメントに置き換えた場合a = x+1、関数内のaの値は、コード内に表示されるポイントで発生したxよりも1つ大きくなりa = x+1ます。値aを使用するポイントに、xという名前の他のローカル変数がたまたま存在したかどうかは関係ありません。同様に、関数を定義した場合int f() { return x + 1; }、xはグローバル変数xを参照しますが、f()が呼び出された場所にたまたま存在するxという名前の他のローカル変数は参照しません。これがやみくもに明白に思える場合、それは、私が言ったように、ほとんどすべての言語が字句スコープを使用しているためです(たとえば、Perlはlocal関数を使用した動的スコープも許可します)。

概念のもう少しの説明については、http://en.wikipedia.org/wiki/Scope_ (computer_science)#Lexical_scoping_and_dynamic_scopingを参照してください。

于 2012-07-18T03:31:59.993 に答える
1

彼らのポイントは、aが参照するxはb()ではローカルですが、c()ではグローバルであるということです-動的にスコープされます。#defineは、「動的スコープを使用してaを評価するときにxを解決する」と解釈できます。

于 2012-07-18T03:39:52.397 に答える