1.方法速记
直接编译语法:将text.c文件或者text.cpp文件直接编译成text文件。
- gcc text.c -o text // gcc-o text.c text
- g++ text.cpp -o text // g++ text.cpp -o text
- 注意:-o后面一定对应着目标文件(可执行文件)就好啦。
2.具体过程
2.1 预处理阶段
预处理的过程就是头文件包含,去注释,宏替换的过程。
预处理指令是以#开头的代码行。
将text.c文件预处理后变成text.i文件
- gcc -E text.c -o text.i
-E的选项是让gcc在预处理结束后就停止编译。
观察可以看到,预处理过后的文件800多行,头文件被包含在里面,并且观察main里面,具体的注释已经被去掉。
2.2 编译阶段
编译阶段是指将预处理后的代码变成汇编语言。
将text.c变成text.s或者将text.i变成text.s:
- gcc -S text.i -o text.s
-S:从现在开始进行编译,如果编译成功就停止下来。
2.3 汇编阶段
将汇编语言变成二进制代码。
将text.c/text.s文件变成text.o文件:
- gcc -c text.s -o text.o
- .o文件又叫可重定位目标文件。
-c:从现在开始进行程序的翻译,如果汇编完成,就停下来。
使用od -x 文件命令,查看机器代码:
2.4链接阶段
将汇编阶段生成的.s文件转成目标文件(可执行文件)。
将text.o文件链接成可执行文件text:
- gcc text.o -o -text
2.4.1 链接的细节
链接:动态链接和静态链接。
动态链接是将库(动态库.so)中我要的方法地址,填入我的可执行程序中,建立关联。(节省资源)
静态链接是直接将库(静态库.a)中的方法真的拷贝到我们的可执行程序中。(占用资源)
gcc或者g++默认使用动态链接编译过程。
- 查看文件链接属性
- file 文件名
- 将源程序采用静态链接的策略
- gcc text.c -o text-s -static
-static:生成的目标文件采用静态链接
观察到文件大小差异很大。
在C程序中,并没有定义"printf"函数的实现,并且在预编译中的“stdio.h”头文件中只有该函数的声明,并没有该函数的实现,那么程序是如何运行"printf"的呢?
事实上,gcc默认是动态链接,预处理把printf函数的声明放到.i文件后,链接阶段可以根据该函数的声明(该函数定义的地址)找到函数的实现,从而实现连接过程。
可以使用ldd指令查看程序链接动态库的情况: