读书频道 > 系统 > linux > 深度探索Linux操作系统系统构建和原理解析
2.1.1 预编译
2013-09-28 11:45:30     我来说两句 
收藏    我要投稿   
全书一共8章:第1章介绍了如何准备工作环境。在第2章中构建了编译工具链,这是后面构建操作系统各个组件的基础。在这一章中,不仅详细讲解了工具链的构建过程,而且还通过对编译链接过程的探讨,深入讨论了工具链  立即去当当网订购

在预编译阶段,预编译器将处理源代码中的预编译指令。一般而言,C语言中的预编译指令以“#”开头,常用的预编译指令包括文件包含命令“#include”、宏定义“#define”,以及条件编译命令“#if”、“#else”、“#endif”等。

在工具链中,一般都提供单独的预编译器,比如GCC中提供的预编译器为cpp。但是,因为预编译也可以看作编译过程的第一遍(first pass),是为编译做的一些准备工作,所以通常编译器中也包含了预编译的功能。如在前面的编译过程中,我们看到gcc并没有单独调用cpp,而是直接调用cc1进行编译,原因就在于此。

以下面的程序为例,该程序使用了典型的预编译指令,我们通过观察这个程序的预处理的结果,来直观体会预编译过程。
foo.h:
#ifndef _FOO_H_
#define _FOO_H_
#define PI 3.1415926
#define AREA
struct foo_struct {
    int a;
};
#endif
hello.c:
#include "foo.h"
int main(int argc, char *argv[])
{
    int result;
    int r = 5;
#ifdef AREA
    result = PI * r * r;
#else
    result = PI * r * 2;
#endif
}

我们可以使用选项-E告诉编译器仅作预处理,不进行编译、汇编和链接,具体命令如下:

gcc -E hello.c -o hello.i

预编译后的结果保存在文件hello.i中,其内容如下:
struct foo_struct {
    int a;
};
int main(int argc, char *argv[])
{
    int result;
    int r = 5;
    result = 3.1415926 * r * r;
}

根据预编译后的结果可见,典型的预编译指令按照如下方式进行处理。

(1)文件包含

文件包含命令指示预编器将一个源文件的内容全部复制到当前源文件中。在上面的代码中,hello.c使用命令“#incude”指示预编器包含文件foo.h。而在预处理的输出文件hello.i中,结构体foo_struct的定义确实已经被复制到了文件hello.i中,也就是说,文件foo.h中的内容被包含到了文件hello.i中。

(2)宏定义

宏可以提高程序的通用性和易读性,减少不一致性和输入错误,便于维护。在预处理过程中,预编器将宏名替换为具体的值。比如,在hello.c的main函数中,经过预处理后,宏名PI已经被替换为具体的值3.1415926。

(3)条件编译

在大多数情况下,源程序中所有的语句都参加编译,但有的时候用户希望按照一定的条件去编译源程序的不同部分,这时可以使用条件编译。比如在函数main中,当定义了变量AREA时,编译器将编译“#ifdef”块的代码,否则编译“#else”块的代码。在上面代码中,因为在foo.h中定义了变量AREA,所以,在经过预处理的文件hello.i中,条件编译指令中的“#else”块的代码从源代码中被删除了,只保留了“#ifdef”块的代码。

点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:2.1 编译过程
下一篇:2.1.2 编译
相关文章
图文推荐
3.3.6 GNOME的软件管
3.3.5 GNOME的文件管
3.3.4 GNOME的窗口管
3.3.3 收藏夹和快捷
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站