以下是两段 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()
的位置来输出不同的值?
答案 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作为练习。