被隐藏了的过程
C语言经典,“Hello World”耳熟能详,是每个人程序入门和开发环境测试的默认标准。
1 #include <studio.h> 2 3 int main() 4 { 5 printf("Hello World"); 6 return 0; 7 }
在Linux下,我们用gcc编译该程序(假设文件名为hello.c),只需要用最简单的命令.
$gcc hello.c $./a.out Hello World
但是,事实上,其中包含了4个步骤:预处理、编译、汇编、链接。
预处理
预处理过程将处理源代码中以“#”开始的预编译指令,生成文件以.i为拓展名。相当于执行语句(-E表示只进行预编译;-o 表示命名)
$gcc -E hello.c -o hello.i
或者
$cpp hello.c > hello.i
预编译过程中的主要处理规则如下:
- 将所有的“#define”删除,并展开所有的宏定义
- 处理所有的预编译指令,如“#if”,“#ifdef”等
- 处理“#include”指令,将被包含的文件插入到该指令位置。该过程是递归进行
- 删除所有的注释
- 添加行号和文件名标识
- 保留所有的#pragma指令
当我们无法判断宏定义是否正确或头文件包含是否正确是,可以选择查看预编译文件
编译
编译过程就是讲预处理完的文件进行一系列的词法、语法、语义分析以及优化后产生相应的汇编代码文件。(推荐看龙虎鲸)
编译过程相当于执行如下指令:
$gcc -S hello.i -o hello.s
在执行该语句时,gcc会根据不同参数要求去调用预编译编译程序cc1,汇编器as,链接器ld。
汇编
汇编是将汇编代码转变成机器可执行的指令。一般是根据汇编指令和机器指令的对照表意义翻译。该过程相当于执行语句:
$as hello.s -o hello.o
或
$gcc -c hello.s -o hello.o
链接
链接的过程比较复杂,我们会在后续文章中详细介绍。简单说,就是将汇编器产生的目标文件进行链接得到可执行文件。
2017-08-06