我们编写好 C++ 语言 的程序后,需要运行 C++ 程序,必须要经过编译与链接的过程。
C++ 语言代码由固定的词汇按照固定的格式组织起来,简单直观,程序员容易识别和理解,但是对于 CPU,C++ 语言代码就是天书,根本不认识,CPU 只认识几百个二进制形式的指令。这就需要一个工具,将 C++ 代码转换成 CPU 能够识别的二进制指令,也就是将代码加工成 .exe 程序的格式。这个工具是一个特殊的软件,叫做编译器(Compiler)。
编译器能够识别代码中的词汇、句子以及各种特定的格式,并将他们转换成计算机能够识别的二进制形式,这个过程称为编译。
编译也可以理解为 “翻译”,类似于将中文翻译成英文、将英文翻译成象形文字,它是一个复杂的过程,大致包括词法分析、语法分析、语义分析、性能优化、生成可执行文件五个步骤,期间涉及到复杂的算法和硬件架构。
代码语法正确与否,编译器说了才算,C++ 的编译器有很多种,不同的平台下有不同的编译器,例如:
C++ 代码经过编译以后,并没有生成最终的可执行文件(.exe 文件),而是生成了一种叫做目标文件(Object File)的中间文件(或者说临时文件)。目标文件也是二进制形式的,它和可执行文件的格式是一样的。对于 Visual C++,目标文件的后缀是 .obj
,对于 G++,目标文件的后缀是 .o
。
目标文件经过链接(Link)以后才能变成可执行文件。既然目标文件和可执行文件的格式是一样的,为什么还要再链接一次呢,直接作为可执行文件不行吗?
不行的!因为编译只是将我们自己写的代码变成了二进制形式,它还需要和系统组件(比如标准库、动态链接库等)结合起来,这些组件都是程序运行所必须的。
链接(Link)其实就是一个 “打包” 的过程,它将所有二进制形式的目标文件和系统组件组合成一个可执行文件。完成链接的过程也需要一个特殊的软件,叫做链接器(Linker)。
随着我们学习的深入,我们编写的代码越来越多,最终需要将它们分散到多个源文件中,编译器每次只能编译一个源文件,生成一个目标文件,这个时候,链接器除了将目标文件和系统组件组合起来,还需要将编译器生成的多个目标文件组合起来。
再次强调,编译是针对一个源文件的,有多少个源文件就需要编译多少次,就会生成多少个目标文件。
不管我们编写的代码有多么简单,都必须经过 “编译 --> 链接” 的过程才能生成可执行文件: