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

Why is the value of macro is not changing in a called function?

我在一个 C 能力问题网站上看到了一个程序

#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

为什么调用fun()i的值没有变成30?

#define i 20

void fun();
 int main(void)
 {
 printf("%d..",i);
 #define i 50       
 printf("%d",i);       
}

但是如果我编译并且 运行 上面的程序输出变成 20..50 那么现在宏值在 运行 时间是如何变化的。

宏无法在运行时更改。在您的程序中,预处理器在编译之前更改了一次宏,因此它在编译程序中的值为 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

实际上是一个空函数

proprocessor 的指令完全独立于程序的普通流程。原因在于 C 标准中指定的 翻译阶段 。处理阶段(阶段 1-4)在正确编译(阶段 7)之前在概念上执行。预处理阶段后获得的单元称为翻译单元,您可以将其视为"starting point"以进行进一步翻译,包括适当的编译。

您的编译器可能允许检查特定的翻译单元,因此您可以有效地了解它的外观。例如 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() {


}