初次使用Visual C++的时候一定有经历过项目的配置,肯定会对预编译头,链接器之类的东西心生疑惑,敲代码就敲代码,怎么有这么多要设置的东西。还有看着Windows版本的程序和Linux版本的编译完成后的文件夹也会疑惑,编译完除了程序怎么还有一堆.obj和.o文件。
首先我们要明白一个流程,程序要运行起来,必须要经过四个步骤:预处理、编译、汇编和链接。每个步骤都会生成对应的文件。像下图一样,接下来我会分成四个步骤描述一下每个步骤都会做什么事
预编译:
预编译如其名,就是编译前的一些准备工作。代码文件放到编译器面前,他肯定也不知道怎么去读,看到头文件他也不知道头文件里是什么,所以预编译就要把一些#define的东西完成文本替换,然后#include的文件里的内容复制到.cpp文件里,如果.h文件里还有.h文件,那递归展开,注释这些编辑器也不管的,完全是给程序员看的。简而言之,就是剔除掉编译器看不懂的东西,然后把所有头文件展开的一个过程。
编译:
编译只是把我们写的代码转为汇编代码,它的工作是检查词法和语法规则,所以,如果程序没有词法或则语法错误,那么不管逻辑是怎样错误的,都不会报错。
汇编:
汇编代码转换机器码,这个阶段,非底层的程序员不需要考虑, 编译器不会搞错的。也与c/c++开发者无关,但是我们可以利用反汇编来调试代码,学习汇编语言依然是必备的。
链接:
配置链接库的重要性就体验在这里,配置的静态链接库还是动态链接库都会在这部分和最后的程序链接到一起。
在这之前引用百度过来的一段话介绍下静态链接和动态链接的区别
静态链接是由链接器在链接时将库的内容加入到可执行程序中的做法。链接器是一个独立程序,将一个或多个库或目标文件(先前由编译器或汇编器生成)链接到一块生成可执行程序。静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分。
动态链接所调用的函数代码并没有被拷贝到应用程序的可执行文件中去,而是仅仅在其中加入了所调用函数的描述信息(往往是一些重定位信息)。仅当应用程序被装入内存开始运行时,在Windows的管理下,才在应用程序与相应的DLL之间建立链接关系。当要执行所调用DLL中的函数时,根据链接产生的重定位信息,Windows才转去执行DLL中相应的函数代码。
C语言代码经过编译以后,并没有生成最终的可执行文件(.exe 文件),而是生成了一种叫做目标文件(Object File)的中间文件(或者说临时文件)。目标文件也是二进制形式的,它和可执行文件的格式是一样的。对于 Visual C++,目标文件的后缀是.obj
;对于 GCC,目标文件的后缀是.o
。这就是一开始所说的编译完一堆.obj和.o文件的来源。
目标文件经过链接(Link)以后才能变成可执行文件。既然目标文件和可执行文件的格式是一样的,为什么还要再链接一次呢,因为编译只是将我们自己写的代码变成了二进制形式,它还需要和系统组件(比如标准库、动态链接库等)结合起来,这些组件都是程序运行所必须的。链接(Link)其实就是一个“打包”的过程,它将所有二进制形式的目标文件和系统组件组合成一个可执行文件。完成链接的过程也需要一个特殊的软件,叫做链接器(Linker)。
这里还要讲一个东西,C++程序编译的时候其实只识别.cpp文件。每个cpp文件都会分别编译一次,生成一个.o或者.obj文件。这个时候,链接器除了将目标文件和系统组件组合起来,还需要将编译器生成的多个.o或者.obj文件组合起来。
本文相关内容来源:https://blog.csdn.net/qq_20398345/article/details/84317148