为什么宏的值在被调用函数中没有变化?

时间:2015-02-08 13:40:55

标签: c macros

我在一个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 那么现在宏值如何在运行时发生变化。

2 个答案:

答案 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() {


}