一个C语言程序从源文件到可执行文件要经历4个步骤:预处理,编译,汇编,连接。预处理主要完成头文件展开,宏替换,条件编译;编译过程作语法检查和词法分析;汇编过程完成将目标文件转换成汇编文件;链接过程主演完成符号表的建立;
下面主要说一下预处理过程:
1.头文件展开:C语言的头文件形式有两种:#include< > 和 #include" ",两者区别在于包含的文件和搜索路径不同:
#include<stdio.h> | #include"user.h" | |
包含的文件 | 包含的文件是系统文件,位于/home/usr/include | 包含的文件为用户自己写的头文件 |
搜索路径 | 从系统指定的头文件目录找 | 在当前目录找,找不到再去系统目录寻找。也可添加路径,如“../../use.h” |
用户写的头文件也可以通过命令行方式写入:gcc filename.c -I 路径(-I:指定第三方搜索路径);
2.宏替换
细细说一下宏定义和宏函数
(1).宏定义提高代码可读性,提高开发效率:假设实际开发中写一个登陆函数,登陆成功返回0,否则返回1,然后再调用函数中用0和1判断登陆情况,非开发者不知道0和1的意义,我们称其为“幻数”:
int log()
{
if()
{
return 0;
}
else
{
reurn 1;
}
}
用宏定义解决“幻数”:
#define LOG_SUCCESS 0
#define LOG_FAIL -1
(2).宏替换的缺点是:只是简单替换,不做语法检查,不安全
#define MUL(a,b) a*b
这种写法错误,当a=3+4;b=5+6;时,替换的结果为:3+4*5+6=29;显然违背了初衷,所以为了保证正确,为每一个变量加上括号,括号绝对不可以省略:
#define MUL(a,b) (a)*(b)
#define MAX(a,b) ((a)>(b)?(a):(b))
(3).总结宏定义的优缺点:
a.优点:宏定义执行效率高,避免函数寻找入口,分配参数空间传参等一系列过程;宏不占用内存,节省空间;
b.缺点:宏不做语法检查,不安全,不能实现复杂功能
c.与函数相比,在功能简单的时候使用宏函数更好;
3.条件编译
(1).用条件编译加注释:
//添加注释
#if 0
.....
#endif
//删除注释
#if 1
...
#endif
(2).条件执行
#define MAX 100
#ifndef MAX
....
#else
...
#endif
Linux也可以通过命令行导入宏,(-D从外部定义宏):
gcc filename.c -DMAX