如何评估这些宏?
# define i 20
void fun();
int main(){
printf("%d",i);
fun();
printf("%d",i);
return 0;
}
void fun(){
#undef i
#define i 30
}
Run Code Online (Sandbox Code Playgroud)
提供输出为2020但是,
# define i 20
void fun(){
#undef i
#define i 30
}
int main(){
printf("%d",i);
fun();
printf("%d",i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出为3030.请解释.谢谢.
Voi*_*ter 55
无论函数调用如何,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
}
Run Code Online (Sandbox Code Playgroud)
你的第二个代码会变成,
# 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;
}
Run Code Online (Sandbox Code Playgroud)
Car*_*rum 18
根本没有涉及的范围.宏在预处理阶段单独处理,独立于编译阶段,没有C范围的概念.您的示例可以很容易:
#define i 20
void fun();
int main()
{
printf("%d",i);
fun();
printf("%d",i);
return 0;
}
void fun()
{
}
#undef i
#define i 30
Run Code Online (Sandbox Code Playgroud)
和:
#define i 20
#undef i
#define i 30
void fun()
{
}
int main()
{
printf("%d",i);
fun();
printf("%d",i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
你可以从中看出它的行为方式.
预处理器宏没有范围,因为它们不是C语言的一部分.相反,它是一种在编译器正常运行之前运行的搜索替换程序.
预处理器只是通过任何文件,不必是C源文件,当它找到宏调用时,它只是将它替换为宏体中的文本.
预处理程序符号绝对具有一个范围,但是该范围不会与其他范围(例如文件范围)交互。
预处理器符号作用域仅限于单个转换单元。一个#define在一个转换单元有另一个翻译单位上没有关系。
预处理程序符号的范围是该符号后面的指令之后的令牌区域#defines。此后,将根据控制规则识别并扩展宏的出现。预处理程序宏定义不是递归的。如果替换令牌序列包含正在定义的符号的调用,则不会这样识别。这就是为什么作用域在指令之后开始的原因。但是,当重新定义宏时,情况仍然如此。重新定义是特殊的,必须符合与原始定义相同的规则。(相同性的精确规则在标准中)。
预处理器符号的作用域以转换单元的末尾结束,如果受#undef指令限制,则更早。
因此,预处理器符号的范围本质上是翻译单元文本的区域,被视为预处理器令牌流,该符号可在其中进行识别和替换。