2.1被隐藏了的过程
Hello World程序hello.c
#include<stdio.h>
int main(){
printf("Hello World!");
return 0;
}
在Linux下,使用GCC编译和执行Hello World程序时,只需使用最简单的命令。
$ gcc hello hello.c
$ ./hello
Hello World
事实上,上述过程可以分解为4个步骤,分别是预处理(Prepressing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。
2.1.1 预编译
首先,源代码文件hello.c和相关头文件stdio.h等被预编译器cpp预编译成hello.i文件。
$ gcc -E hello.c -o hello.i
或者
$ cpp hello.c>hello.i
预编译过程主要处理那些源文件中以“#”开始的预编译指令。
主要处理规则如下:
- 将所有的“#define”删除,并且展开所有的宏定义。
- 处理所有条件预编译指令,比如“#if”,”ifdef”,”#elif”,“#else”,”endif”。
- 递归处理“#include”预编译指令,将被包含的文件插入到该预编译指令的位置。
- 删除所有的注释“//”和“/**/”。
and so on
2.1.2 编译
编译过程就是把预处理后的文件进行一些列词法分析、语法分析和语义分析,然后优化生成相应的汇编代码文件。
$ gcc -S hello.i -o hello.s
或者
$ ccl hello.c
关于GCC命令:对于C语言来说,预编译和编译的程序是ccl,对于C++来说,对应程序是cclplus;所以,实际上gcc这个命令只是这些后台程序的包装,它会根据不同的参数要求去调用预编译编译程序ccl、汇编器as、连接器ld。
2.1.3 汇编
汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令,只需根据汇编指令和机器指令的对照表一一翻译即可。
$ as hello.s -o hello.o
或者
$ gcc -c hello.c -o hello.o
这里,hello.o文件已经是二进制机器码,不能使用vim打开。但是可以使用nm命令打开,nm命令被用于显示二进制目标文件的符号表。
$ nm hello.o
2.1.4 链接
为什么汇编器不直接输出可执行文件而是输出一个目标文件呢?链接过程到底包含了什么内容?为什么要链接?
——《程序员的自我修养》