我们知道C的整个编译过程由预处理,编译,链接三个步骤组成。include
命令是在预处理阶段解析的。而
预处理阶段只是进行简单的文本替换
我们先来看看一个简单的预处理过程
main.c
int main()
{
#if 1
int a=1;
int b=2;
int sum = a + b;
#endif
return (1+2);
}
对main.c文件进行预处理 gcc -E main.c -o main.i
# 1 "main.c"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.c"
int main()
{
//对应 main.c 文件此行应该是 #if 1,现在已用空行 替换
int a=1;
int b=2;
int sum = a + b;
//对应 main.c 文件此行应该是 #endif 现在已用空行替换
return (1+2);
}
我们对main.c文件稍加改动
main.c
int main()
{
#if 0 //!!!!!!!!!!!
int a=1;
int b=2;
int sum = a + b;
#endif
return (1+2);
}
我们利用if
宏使得三行代码无效,我们再来看看预处理的结果
# 1 "main.c"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.c"
int main()
{
//我们可以看到,预处理只是将这段无效代码用空行替换
return (1+2);
}
其实,预处理阶段只是进行简单的文本替换
一般情况下我们通过头文件来定义外部接口,然后通过include
宏来引用。这里我们有一个例子
add.h
int notice
#ifndef ADD_H__
#define ADD_H__
int add(int a,int b);
int test = 100;
#endif
add.c
int add(int a,int b)
{
return (a+b);
}
main.c
#include "add.h"
int main()
{
return add(1,1);
}
对main.c文件进行预处理 gcc -E main.c -o main.i
main.i
# 1 "main.c"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.c"
# 1 "add.h" 1
int notice; //头文件add.h里面的内容
//ifndef等宏命令,现在已经以空行替换
int add(int a,int b);
int test = 100;
# 2 "main.c" 2
int main()
{
return add(1,2);
}
我们可以看到我们通过include
引入了add.h
里面的内容到main.c
头文件里有下面几行
#ifndef ...
#define ...
.....
#endif
是用来防止头文件重复包含的
现在我们再来看一下
main.c
#include "add.h"
#include "add.h"
int main()
{
预处理后的结果
main.i
# 1 "main.c"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.c"
# 1 "add.h" 1
int notice; //头文件add.h里面的内容
//ifndef等宏命令,现在已经以空行替换
int add(int a,int b);
int test = 100;
# 2 "main.c" 2
# 1 "add.h" 1
int notice; //此处在ifndef等宏命令之前,所以被复制过来了,我们可以看到,因为此时ADD_H__已经被定义,所以内容以空替换
# 3 "main.c" 2
int main()
{
return add(1,2);
}
另外我们可以发现,notice变量被重定义了。
所以include
命令会无条件的引入文本文件,但是我们可以通过
#ifndef ...
#define ...
.....
#endif
方法防止文件里面的内容被重新包含(复制)。
预处理阶段只是进行简单的文本替换,而有了这几种宏命令,我们便可以更灵活的设置文件的包含过程。
预处理阶段只是进行简单的文本替换 其实不完全对,但是对于我们理解一些简单的宏命令是足够的。