处理这两段代码

时间:2013-08-14 04:20:15

标签: c c-preprocessor

以下是两段 C 代码,但我不明白它们是如何工作的:

计划1:

#include<stdio.h>
#define s 10
fun() {
 #undef s
 #define s 20
}
int main(){
 printf("%d\n",s);
 fun();
 printf("%d\n",s);
 return 0;
}
Output: 20
        20

计划2:

#include<stdio.h>
#define s 10
int main(){
 printf("%d\n",s);
 fun();
 printf("%d\n",s);
 return 0;
}
fun() {
 #undef s
 #define s 20
}
output: 10
        10

我所知道的是预处理器在main()开始之前工作并替换其所有变量。 在fun()之后调用printf(),那么两个程序如何通过更改fun()的位置来输出不同的值?

3 个答案:

答案 0 :(得分:5)

预处理器不关心范围。它按照从上到下的顺序逐行浏览文件,并进行文本替换。如果某些内容为#define d或#undef,则它会从该行生效,直到文件的底部(或其他预处理程序语句覆盖它)。

答案 1 :(得分:5)

宏将在编译时自行替换。所以在预处理后代码就像这样,

案例1:

#include<stdio.h>

fun() {
}
int main(){
 printf("%d\n", 20);//latest definition of s will be considered.
 fun();
 printf("%d\n",20);
 return 0;
}

案例2:

#include<stdio.h>

int main(){
 printf("%d\n",10); //replaced with 10 only, because in this instance, there is no change in s 
 fun();
 printf("%d\n",10);
 return 0;
}
fun() {
 //#undef s
 //#define s 20 //no use in ur code. 
}

fun_extra() { //Added for demo
   printf("%d\n",s);//will be replaced by 20. 
}

答案 2 :(得分:3)

预处理程序语句不可执行。他们是......好吧,经过预处理。这意味着编译器将执行初始单次传递并解析所有预处理定义。如果预处理定义位于C控制结构内,则无论C控制结构的含义如何,都将执行它。换句话说,从预处理器的角度来看,没有C代码。只是文本(和其他预处理器语句)。

在你的情况下,在第一遍:

#include<stdio.h>     // File stdio.h is included/copied
#define s 10          // Preprocessor symbol s is defined as 10
fun() {               // Copied literally
    #undef s          // Preprocessor symbol s is undefined
    #define s 20      // Preprocessor symbol s is defined as 20
}                     // Copied literally
int main(){           // Copied literally
   printf("%d\n",s);  // Copied with s substituted, ie. printf("%d\n",20);
   fun();             // Copied literally
   printf("%d\n",s);  // Copied with s substituted, ie. printf("%d\n",20);
   return 0;          // Copied literally
}                     // Copied literally

因此,真正编译的输入是:

// Empty line originally corresponding to #include
// Empty line originally corresponding to #define
fun() {
    // Empty line originally corresponding to #undef
    // Empty line originally corresponding to #define
}
int main(){
   printf("%d\n",20);
   fun();
   printf("%d\n",20);
   return 0;
}

请注意,fun函数不包含任何 C指令。在预处理之前,它确实包含2个预处理指令,但是:

  • 他们在亲处理后消失了
  • 他们从未真正属于函数fun,因为此时没有函数fun或任何其他C代码。只是文本和预处理器语句。

这项工作通常由C编译器在内部和内部完成。但是,他们中的许多人都有保存预处理源文件的选项。您应该获得如上所示的结果(除了#include<stdio.h>将扩展为许多空白行,以及一些C代码,这里我将其作为一个空行标记)。

第二种情况留给OP作为练习。