C中宏的范围?

如何评估这些宏?

# define i 20 void fun(); int main(){ printf("%d",i); fun(); printf("%d",i); return 0; } void fun(){ #undef i #define i 30 } 

给出产量为2020但是,

 # define i 20 void fun(){ #undef i #define i 30 } int main(){ printf("%d",i); fun(); printf("%d",i); return 0; } 

输出为3030.请解释。 谢谢。

无论函数调用如何,C预处理器都从上到下工作。 无论宏定义的文件是什么,从该点(线)开始都是有效的,直到对应的undef或者直到翻译单元的末尾。

那么,你的代码会变成,

 # define i 20 // from now on, all token i should become 20 void fun(); int main() { printf("%d",i); // printf("%d",20); fun(); printf("%d",i); // printf("%d",20); return 0; } void fun() { #undef i // from now on, forget token i #define i 30 // from now on, all token i should become 30 } 

你的第二个代码会变成,

 # define i 20 // from now on, all token i should become 20 void fun() { #undef i // from now on, forget i #define i 30 // from now on, all token i should become 30 } int main() { printf("%d",i); // printf("%d",30); fun(); printf("%d",i); // printf("%d",30); return 0; } 

根本没有涉及范围 。 宏在预处理阶段单独处理,独立于编译阶段,没有C范围的概念。 您的示例可以很容易:

 #define i 20 void fun(); int main() { printf("%d",i); fun(); printf("%d",i); return 0; } void fun() { } #undef i #define i 30 

和:

 #define i 20 #undef i #define i 30 void fun() { } int main() { printf("%d",i); fun(); printf("%d",i); return 0; } 

你可以从中看出它的行为方式。

根本没有范围。

宏由预处理器代替。 因此,他们的扩张是由他们在源头中从上到下的位置来定义的。

预处理器宏没有范围,因为它们不是C语言的一部分。 相反,它是一种在编译器正常运行之前运行的搜索替换程序。

预处理器只是通过任何文件,不必是C源文件,当它找到宏调用时,它只是将它替换为宏体中的文本。

宏在编译之前的单独阶段中对源文本生效。 宏在编译代码中不再以任何forms存在,并且在运行时不会对它们进行求值。

调用宏时(在源的文本扫描期间),无论宏定义有效,都将被替换为源文本。

预处理程序符号绝对具有范围,但该范围不与其他范围(如文件范围)交互。

预处理器符号范围仅限于单个转换单元。 一个翻译单元中的#define与另一个翻译单元无关。

预处理程序符号的范围是遵循指令的标记区域,# #defines它的符号。 此后,根据管理规则识别和扩展宏的发生。 预处理器宏定义不是递归的。 如果替换标记序列包含的内容类似于正在定义的符号的调用,则不会将其识别为这样。 这就是范围在指令之后开始的原因。 但是,重新定义宏时仍然如此; 重新定义是特殊的,必须符合与原始定义相同的规则。 (相同的准确规则在标准中)。

预处理程序符号的范围以转换单元的结尾结束,如果它受#undef指令约束,则更早。

因此,预处理器符号的范围基本上是翻译单元文本的区域,被视为预处理器令牌流,其中该符号有资格用于识别和替换。

在C预处理器阶段评估宏。 C预处理器阶段与编译阶段分开进行。 因此,宏不遵循常规范围。 而是按照它们在源文件中出现的顺序进行评估(因此从顶部到底部)。

在你的第一个代码示例中,它输出2020,尽管它在main函数中调用fun(),它应该将i的值更改为30,但由于fun函数出现在调用它的下方,因此值不会像预处理器那样改变尚未到达那一点。

在第二个代码示例中,它输出3030,因为fun函数位于main函数之上。 因此,当预处理器已经通过fun函数并将i的值更改为30时,会发生相反的情况