四个阶段:预编译、编译、汇编和链接。
阶段 | 输入 | 输出 | 工具 | 示例 |
预编译 | *.c | *.i | 预处理器cpp | gcc –E test.c –o test.i |
编译 | *.i | *.s 汇编代码 | 编译器egcs | gcc –S test.i –o test.s |
汇编 | *.s | *.o 目标代码 | 汇编器as | gcc –c test.s –o test.o |
链接 | *.o | 可执行文件 | 连接器ld | gcc test.o –o test |
简单理解:
预编译:替换宏定义的变量和include包含以及进行条件编译;即如#define PI 3.1415,则将文件中的PI用3.1415替换,include文件包含和条件编译同理。
编译:生成汇编语言。
汇编:生成机器语言。
链接:生成可执行程序。
执行过程示例(百度百科)
示例代码 a.c:
#include <stdio.h>
int main()
{
printf("hello\n");
}
预编译过程:
这个过程处理宏定义和include,并做语法检查。
可以看到预编译后,代码从5行扩展到了910行。
gcc -E a.c -o a.i
cat a.c | wc -l
5
cat a.i | wc -l
910
编译过程:
这个阶段,生成汇编代码。
gcc -S a.i -o a.s
cat a.s | wc -l
59
汇编过程:
这个阶段,生成目标代码。
此过程生成ELF格式的目标代码。
gcc -c a.s -o a.o
file a.o
a.o: ELF 64-bit LSB relocatable, AMD x86-64, version 1 (SYSV), not stripped
链接过程:
链接过程。生成可执行代码。链接分为两种,一种是静态链接,另外一种是动态链接。使用静态链接的好处是,依赖的动态链接库较少,对动态链接库的版本不会很敏感,具有较好的兼容性;缺点是生成的程序比较大。使用动态链接的好处是,生成的程序比较小,占用较少的内存。
gcc a.o -o a
程序运行:
./a
hello