c - C 宏的作用域规则

标签 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(); }

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

谁能澄清一下?

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

最佳答案

您对#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以获得对该概念的更多解释。

关于c - C 宏的作用域规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11533771/

相关文章:

c - 为什么 sizeof(param_array) 是指针的大小?

c++ - 预处理字符串连接

c - 如何在预处理器宏中对算术结果进行字符串化

c++ - 如何通过 C++ 宏调用编译时错误?

c - 在引号中使用定义宏及其值

c - 十六进制 IP 到十进制 IP 转换

c++ - raise(SIGABRT) 和 abort() 方法之间的区别

c - 使用 C 替换文件中的单词

c - 如何给STM32F4写一个时差函数

java - Android 有用的调试/发布宏(使用 gradle?)