2015-02-08 76 views
-1

我碰到一个项目来了一架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 

为什么多申” t i的值在拨打fun()后变为30?

#define i 20 

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

但是,如果我编译并运行上述程序的输出变成20..50 那么现在怎么宏值在运行时更改。

+0

答案在于预处理器和编译器之间的区别。搜索网络的一些信息,它应该很清楚。 – 2015-02-08 13:43:59

+0

在运行程序之前,甚至在编译之前处理宏。让你的编译器写出“预处理”的代码,你会看到“我”做什么。 (另外:绝对不要在“define”中包含分号,用你明显的经验水平,你**会得到一些令人讨厌的惊喜!) – usr2564301 2015-02-08 13:45:52

回答

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 

使用上述预处理程序实际上是一个空函数

+0

但是如果你喜欢printf(“%d ..”,i); #define i 50 printf(“%d”,i);输出变为20..50 – 2015-02-08 13:44:31

+0

'#define i 50 printf(“%d”,i)'?完全像那样?如果您有这样的情况,请将其添加到您的问题中,以帮助您解释实际发生的情况。 – 2015-02-08 13:46:11

+3

甚至在编译器在运行时间之前看到代码之前,宏也被替换(如纯文本替换)与它们的定义。如果您重新定义了一个宏,那么对于代码文件中低于重定义的所有代码,其值将会改变,但是它之前没有。如果你把一个'printf(“%d \ n”,i);在第二个'#define'之后的'fun'中,你会得到输出'20 50 20'。 – Wintermute 2015-02-08 13:52:40

3

的proprocessor的指示是完全独立的,独立于程序的普通流。原因在于在C标准中指定的翻译阶段。处理阶段(阶段1-4)在正确汇编(阶段7)之前在概念上进行。预处理阶段后获得的单位被称为翻译单位,您可以将其作为进一步翻译的“起点”,包括正确的编译。

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


}