C宏的范围规则

我不是一个C程序员,但我假设C宏几乎是一种查找和替换function,其中预处理器采用宏定义并将其放在它看到宏名称的任何地方。

这是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(); } 

他们还讨论了动态范围规则如何应用于宏a的名称x 。 我假设它基本上会替换with (x + 1)然后编译程序,因此范围规则与写入(x + 1)而不是a (它将是静态的(x + 1)完全相同范围规则)。

任何人都可以澄清一下吗?

编辑:书中提到的是编译器:原理,技术和工具第二版。 引用的例子来自第31-32页。

您对#define行为的理解是正确的。

我认为这本书的意思是什么,当它说“动态范围”时,名称x是根据调用宏的环境而不是在其定义的位置解析的。 因此,如果你在#define之前设置了一个全局变量x = 3,这与#define中x的值无关 – 它只会在你使用宏的地方使用x的值 – 如果有其他本地的话在使用宏的函数中的变量x,将使用本地值。

这与词汇范围(在C语言和几乎所有现代语言中实际使用的词汇)形成对比,其中名称指的是其本地词汇环境。 例如,如果您通过简单语句a = x+1替换了示例中的#define,那么函数中a的值将比x a = x+1出现的点处a = x+1在代码中。 如果名为x的其他局部变量恰好存在于使用值a的位置,则无关紧要。 同样,如果你定义了一个函数int f() { return x + 1; } int f() { return x + 1; } ,x将引用全局变量x,而不是在调用f()时恰好存在的其他名为x的局部变量。 如果这看起来非常明显,那是因为,正如我所说的,几乎所有语言都使用词法范围(例如,Perl也允许使用local函数的动态范围)。

有关该概念的更多解释,请参见http://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping_and_dynamic_scoping 。

您的理解是正确的:找到标识符a每次使用,并用(x + 1)替换a 。 这正是预处理器的作用。

我们可以讨论的关于类对象宏(如a )的唯一“范围”是宏本身的范围 :宏的范围来自定义它的行(使用#define指令)直到它未定义的行(使用#undef指令)或直到翻译单元的末尾(.cpp及其包含的所有头文件),如果它从未未定义。

他们的观点是a引用的x是b()中的局部,但是c()中的全局 – 它是动态范围的。 #define可以解释为“在评估a时使用动态范围来解析x”。