2

这是两段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

方案二:

#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()

4

3 回答 3

5

预处理器不关心范围。它只是按从上到下的顺序逐行遍历文件,并进行文本替换。如果某些内容是#defined 或#undefined,它将从该行开始生效,直到文件底部(或另一个预处理器语句覆盖它)。

于 2013-08-14T04:26:54.953 回答
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;
}

案例二:

#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. 
}
于 2013-08-14T04:28:08.950 回答
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 作为练习。

于 2013-08-14T04:24:01.427 回答