--事物的难度远远低于对事物的恐惧!
本章节我们来聊一聊编译过程,我们写代码通常会用现成的集成开发环境,比如vs2010等,写完后一键编译,就能获取我们想要的可执行文件,那么在这一键编译的过程中,发生了什么?编译是个怎样的过程?要想了解这个过程,我们首先来了解下编译器。
编译器大概可由如下几个部分组成:
由图我们可以得知,编译器由 预处理器、编译器、汇编器、链接器组成,而编译过程,则可参考如下的这张图:
从图中可看到,代码从源程序到目标文件,经过的步骤比较负责,下边我们来逐一分析:
预编译:
-处理所有的注释,用空格代替
-将所有的#define删除,并且展开所有的宏定义
-处理条件编译指令#if,#ifdef,#elseif,#else,#endif等
-处理#include,展开被包含的文件
-保留编译器需要使用的#pragma指令
gcc中预编译指令为:gcc -E file.c -o file.i
VC中的预编译指令为:cl -E file.c > out.i
下边来看个示例:
//header.h char* p = "Delphi"; int i = 0;
//main.c #include "header.h" // Begin to define macro #define GREETING "Hello world!" #define INC(x) x++ // End int main() { p = GREETING; INC(i); return 0; }vs2010下使用预编译器进行与编译,cl -E main.c > main.i,main.i文件的内容如下:
#line 1 "main.c" #line 1 "f:\\study\\c\\header.h" char* p = "Delphi"; int i = 0; #line 2 "main.c" int main() { p = "Hello world!"; i++; return 0; }
从main.i的内容,我们可以知道,头文件被展开了、注释去掉了、#define去掉了,并且在对应的位置作了宏替换
编译:
-在预编译完成后,就由编译器对预编译完成的文件进行词法分析、语法分析和语义分析
-词法分析:分析关键字,标识符,立即数等是否合法
-语法分析:分析表达式是否遵循语法规则
-语义分析:在语法分析的基础上进一步分析表达式是否合法
-分析结束后进行代码优化生成相应的汇编代码文件
gcc中的编译指令为:gcc -S file.c -o file.s
汇编:
-汇编器将编译得到的汇编代码转变为机器可以执行的指令
-每条汇编语句几乎都对应一条机器指令
总结:
编译过程分为预处理,编译,汇编和链接四个阶段
-预处理:处理注释,宏以及已经以#开头的符号
-编译:进行词法分析,语法分析和语义分析
-汇编:将汇编代码翻译为机器指令的目标文件