C宏的范围规则

时间:2012-07-18 03:12:58

标签: c macros

我不是一个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中的名称a。我假设它基本上用a替换(x + 1)然后编译程序,因此范围规则与编写(x + 1)而不是{{}的范围完全相同1}}(这将是静态范围规则)。

有人可以澄清这个吗?

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

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

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

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

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

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

答案 2 :(得分:1)

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