我不是一个 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
with (x + 1)
然后编译程序,因此范围规则将与您编写的完全相同(x + 1)
代替a
(这将是静态范围规则)。
有人能澄清一下吗?
编辑:所指的书是《编译器:原理、技术和工具第二版》。引用的示例来自第 31-32 页。
您对 #define 行为的理解是正确的。
我认为这本书所说的“动态作用域”的意思是名称 x 是根据调用宏的环境而不是定义它的环境来解析的。因此,如果您在 #define 之前设置了全局变量 x=3,则这与 #define 中 x 的值无关 - 无论您使用宏,它都会使用 x 的值 - 如果还有其他本地变量如果在使用宏的函数中使用变量 x,则将使用本地值。
这与词法作用域(C 语言和几乎所有现代语言中实际使用的)形成鲜明对比,在词法作用域中,名称指的是其本地词法环境。例如,如果您将示例中的 #define 替换为简单语句a = x+1
,那么函数中 a 的值将比此时 x 的值大 1a = x+1
出现在代码中。如果您使用值 a 时碰巧存在其他名为 x 的局部变量,也没关系。类似地,如果你定义了一个函数int f() { return x + 1; }
, x 将引用全局变量 x,而不是调用 f() 时恰好存在的其他名为 x 的局部变量。如果这看起来非常明显,那是因为,正如我所说,几乎所有语言都使用词法作用域(尽管 Perl 也允许使用动态作用域)local
功能)。
See http://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping_and_dynamic_scoping对这个概念有更多的解释。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)