从 C 或 C++ 源文件创建应用程序的基本步骤如下:
(1) 源文件被创建(由人或程序生成),(2) 源文件被编译(实际上是两个步骤,预处理器和编译)成目标代码,(3) 目标文件是由 C/C++ 编译器创建的链接来创建 .exe
因此,您拥有将计算机程序的一个版本(源文件)转换为另一个版本(可执行文件)的这些步骤。编译 C++ 源代码以生成目标文件。然后链接目标文件以生成可执行文件。
在大多数情况下,C 和 C++ 的编译和链接过程涉及多个不同的程序。每个程序都接收某些文件并创建新文件。
- C/C++ Preprocessor 获取源代码文件并生成源代码文件
- C/C++ 编译器接收源代码文件并生成目标代码文件
- 链接器接收目标代码文件和库并生成可执行文件
见What is the difference between - 1) Preprocessor,linker, 2)Header file,library? Is my understanding correct?
大多数编译器安装都有一个程序为您运行这些不同的应用程序。因此,如果您使用的是gcc,那么gcc 程序将首先运行 C++ 预处理器,然后是 C++ 编译器,然后是链接器。但是,您可以修改 gcc 使用命令行选项所做的操作,以告诉它仅运行 C++ 预处理器或仅编译源文件但不链接它们或仅链接目标代码文件。
计算机语言和编程简史
多年来,用于计算机编程的语言以及各种软件开发工具不断发展。
第一台计算机通过控制台上的开关输入的数字进行编程。
然后人们开始开发可用于更轻松、更快速地创建软件的语言和软件。第一个主要发展是创建汇编语言,其中每一行源代码都由计算机程序转换为机器代码指令。随之而来的是链接器的开发(将机器代码片段链接成更大的片段)。通过添加宏或预处理器工具来改进汇编器,这有点像 C/C++ 预处理器,虽然是为汇编语言设计的。
然后人们创建的编程语言看起来更像是人们编写的语言而不是汇编语言(例如 FORTRAN 和 COBOL 和 ALGOL)。这些语言更容易阅读,单行源代码可能会被转换成多个机器指令,因此用这些语言而不是汇编语言编写计算机程序更有效率。
C 编程语言是后来利用从早期编程语言(如 FORTRAN)中吸取的经验进行的改进。 C 使用了一些已经存在的相同软件开发工具,例如已经存在的链接器。再后来,C++ 被发明出来,开始是对 C 的改进,引入了面向对象的工具。事实上,第一个 C++ 编译器实际上是一个 C++ 翻译器,它将 C++ 源代码翻译成 C 源代码,然后用 C 编译器编译。然而,现代 C++ 直接编译为机器代码,以便通过模板、lambda 以及 C++11 及更高版本的所有其他内容提供 C++ 标准的全部功能。
链接器和加载器
当你运行一个程序时,你运行的是可执行文件。可执行文件包含多种信息。第一个是机器指令,它是编译 C++ 源代码的结果。另一个是加载器用来知道如何将可执行文件加载到内存中的信息。
在过去,很久很久以前,所有的库和目标文件都被链接到一个可执行文件中,并且可执行文件由加载器加载,加载器非常简单。
后来人们发明了共享库和动态链接库,这就要求链接器更复杂,加载器更复杂。
链接器变得更加复杂,因为它必须能够识别使用共享库和静态库之间的区别,并能够生成一个可执行文件,该文件不仅包含链接的目标代码,还包含有关加载程序的信息任何动态库。
加载器变得更加复杂,因为加载器不仅必须将可执行文件加载到内存中以便它可以开始运行,加载器还必须找到任何也需要的共享库或动态链接库并加载它们。并且加载器还必须对附加组件(共享库)进行一定量的链接,因此加载器所做的工作比过去要多得多。
另见