我在一个C aptitude问题网站上看到了一个程序
#define i 20
void fun();
int main(void)
{
printf("%d..",i);
fun();
printf("%d",i);
}
void fun() {
#undef i;
#define i 30
}
此处输出为
20..20
但据我说它应该是
20..30
调用i
后,为什么fun()
的价值变为30?
#define i 20
void fun();
int main(void)
{
printf("%d..",i);
#define i 50
printf("%d",i);
}
但是如果我编译并运行上面的程序,输出变为20..50 那么现在宏值如何在运行时发生变化。
答案 0 :(得分:5)
无法在运行时更改宏。在您的程序中,宏在编译之前由预处理器更改一次,因此它在编译的程序中的值为30
。
您可以阅读here。
void fun() {
#undef i;
#define i 30
}
实际上是一个空函数,预处理程序将是
void fun();
int main(void)
{
printf("%d..",20);
fun();
printf("%d",20);
}
void fun() {
}
所以你可以看到输出是正确的。
要生成上述预处理计划,您可以将其与gcc
gcc -E -P source.c
实际上是一个空函数
答案 1 :(得分:3)
Proprocessor的指令完全独立,与程序的普通流程分开。其原因在于转换阶段,它们是在C标准中指定的。在适当编译(阶段7)之前,在概念上执行处理阶段(阶段1-4)。预处理阶段后获得的单元称为翻译单元,您可以将其视为进一步翻译的“起点”,包括正确的编译。
您的编译器可能允许检查特定的翻译单元,因此您可以了解它的有效性。例如gcc
有-E
标志(默认情况下,它会输出所谓的linemarkers,但您可以使用-P
标志来抑制它们)。在您的情况下,它可能看起来像:
$ gcc -E test.c
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
void fun();
int main(void)
{
printf("%d..",20);
fun();
printf("%d",20);
}
test.c:13:9: warning: extra tokens at end of #undef directive
void fun() {
}