预处理、编译、汇编、链接

一个c/c++文件要经过预处理、编译、汇编和链接才能变成可执行文件。我们经常把前三个步骤统称为编译了。

一、预处理

C/C++源文件中,以#开头的命令被称为预处理命令,如包含命令#include、宏定义命令#define、条件编译命令#if、#ifdef等。所做的主要工作如下:

(1)将所有的#define删除,并展开所有的宏定义
(2)处理所有的条件预编译指令,如:#if  #ifdef #elif #else #endif
(3)处理#include预编译指令,将被包含的文件插进到该指令的位置,这个过程是递归的
(4)删除所有的注释//与/* */
(5)添加行号与文件名标识,以便产生调试用的行号信息以及编译错误或警告时能够显示行号
(6)保留所有的#pragma编译器指令,因为编译器需要使用它

二、编译

把预处理完的文件进行一系列词法分析(lex)、语法分析(yacc)、语义分析及优化后生成汇编代码,这个过程是程序构建的核心部分。 

三、汇编

汇编就是将第二步输出的汇编代码翻译成符合一定格式的机器代码,在Linux系统上一般表现为ELF目标文件(OBJ文件)。反汇编是指将机器代码转换为汇编代码,这在调试程序时常常用到。

四、链接

链接就是将上步生成的OBJ文件和系统库的OBJ文件、库文件链接起来,最终生成了可以在特定平台运行的可执行文件。

五、小结


hello.c(预处理)->hello.i(编译)->hello.s(汇编)->hello.o(链接)->hello

详细的每一步命令如下:

gcc -E -o hello.i hello.c
gcc -S -o hello.s hello.i
gcc -c -o hello.o hello.s
gcc -o hello hello.o
上面一连串命令比较麻烦,gcc会对.c文件默认进行预处理操作,使用-c再来指明了编译、汇编,从而得到.o文件, 再将.o文件进行链接,得到可执行应用程序。简化如下:
gcc -c -o hello.o hello.c

gcc -o hello hello.o


对于gcc -o test a.c b.c这条命令 它们要经过下面几个步骤:

1).对于a.c执行:预处理 编译 汇编 的过程,a.c -->xxx.s -->xxx.o 文件。
2).对于b.c执行:预处理 编译 汇编 的过程,b.c -->yyy.s -->yyy.o 文件。
3).最后:xxx.o和yyy.o链接在一起得到一个test应用程序。
提示:gcc -o test a.c b.c -v :加上一个‘-v’选项可以看到它们的处理过程,

第一次编译a.c得到xxx.o文件,这是很合乎情理的, 执行完第一次之后,如果修改a.c 又再次执行:gcc -o test a.c b.c,对于a.c应该重新生成xxx.o,但是对于b.c又会重新编译一次,这完全没有必要,b.c根本没有修改,直接使用第一次生成的yyy.o文件就可以了。

缺点:对所有的文件都会再处理一次,即使b.c没有经过修改,b.c也会重新编译一次, 当文件比较少时,这没有没有什么问题,当文件非常多的时候,就会带来非常多的效率问题。

如果文件非常多的时候,我们,只是修改了一个文件,所用的文件就会重新处理一次,编译的时候就会等待很长时间。

对于这些源文件,我们应该分别处理,执行:预处理 编译 汇编 ,先分别编译它们,最后再把它们链接在一次,比如:

编译:
gcc -o a.o a.c
gcc -o b.o b.c
链接:
gcc -o test a.o b.o

比如:上面的例子,当我们修改a.c之后,a.c会重现编译然后再把它们链接在一起就可以了。b.c 就不需要重新编译。


参考链接:

https://www.cnblogs.com/kekec/p/3238741.html

http://wiki.100ask.org/%E7%AC%AC009%E8%AF%BE_gcc%E5%92%8Carm-linux-gcc%E5%92%8CMakefile

猜你喜欢

转载自blog.csdn.net/wwwlyj123321/article/details/80893105
今日推荐