| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> C++ 程序编译过程:从代码到程序 -> 正文阅读 |
|
[C++知识库]C++ 程序编译过程:从代码到程序 |
????????在大学课堂上学习 C++ 时,老师并没有过多涉猎 C++ 语法背后的知识。也就是说,初学 C++ 时,哪怕写出了代码,我也并不知道从代码到程序的过程中究竟发生了什么。我也曾尝试了解,但作为初学者,面对一堆晦涩难懂的词汇,我也只是看了几眼便放弃了。但知道背后的过程无疑是非常重要的。今日,谨以此文回答我自己学习过程中遇到的问题:C++ 代码是如何变成程序的。 初探 C++ 编译过程????????C++ 程序编译过程一般可以分为三个步骤:
????????其中第二步“编译”的意思并不是指从代码到可执行文件的全过程,而是从 C++ 到 machine code 的过程。我们先对这三个步骤进行初步了解: 预处理? ? ? ? 预处理器 Pre-Processor 接收 C++ 源码文件,处理其中的预处理指令。然后输出一个预处理完毕的文件,文件后缀通常为 i。 编译? ? ? ? 编译器 Compiler 获取预处理器的输出,将其翻译成汇编语言,汇编语言文件通常以 s 作为后缀。然后再将得到的汇编语言文件翻译成 machine code,得到 object file,也就是目标文件,通常以 o 或者 obj 作为后缀,是二进制文件。 链接? ? ? ? 链接器 Linker 获取编译器生成的所有目标文件,然后链接程序所需的外部库文件,最终得到一个可执行文件或者库文件。 ? ? ? ? 值得注意的是,编译阶段实际上可以再分为从 C++ 到汇编,从汇编到 machine code 两步。因此我们最终细分得到的 C++ 程序编译过程如下:
? ? ? ? 该过程如图: ? ? ? ? 接下来,让我们更详细地了解以上四个阶段。 预处理? ? ? ? 预处理阶段获取源文件,处理其中的预处理指令,常见的预处理指令有:
? ? ? ? 预处理指令均以“#”开头,更多预处理指令请参考: Preprocessor directives | Microsoft Docshttps://docs.microsoft.com/en-us/cpp/preprocessor/preprocessor-directives?view=msvc-170&viewFallbackFrom=vs-2019? ? ? ? 在这一阶段,预处理器会根据预处理指令执行相应的操作。例如,#include 指令会让指定文件被包含进预处理文件。宏也会在这一阶段被替换和展开。预处理器处理完所有预处理指令后,生成一个预处理完毕的文件。 编译? ? ? ? 这一阶段主要获取预处理阶段生成的文件,然后将其翻译为汇编代码,得到汇编代码文件。通常来说,我们收到的编译器警告和错误都来自这一阶段。这些警告和错误是由语法错误导致的。 汇编? ? ? ? 这一阶段会获取编译阶段生成的文件,将其进一步翻译为 machine code,得到 object file,也就是目标文件,目标文件本身是二进制文件。此外,如果你一次编译了多个独立文件,那么每一个文件都会生成对应的目标文件。 链接? ? ? ? 链接阶段获取汇编阶段生成的目标文件,将所有目标文件编译成可执行文件或库文件。然后链接器解析依赖项,链接外部静态库,得到最终的可执行文件或库文件。这一阶段最常见的错误是缺少定义或者重复定义,前者由定义不存在或目标文件未给出链接器导致,后者由同一符号在多个目标文件或库文件中重复定义导致。 示例代码? ? ? ? 接下来,我们以 GCC 为例,通过示例,生成各个阶段对应的文件,对编译的过程进行更详细的了解。示例包含三个文件:math.hpp,math.cpp,main.cpp,你可以在任意位置生成它们。 ????????math.hpp:
? ? ? ? math.cpp:
? ? ? ? main.cpp:
? ? ? ? 文件结构如图,math.cpp 文件和 math.hpp 文件位于 include 文件夹内: 预处理文件? ? ? ? 打开命令行,定位到文件所在目录,以我的电脑为例,文件目录为。 ?D:\Workflow\WorkSpace\QuickStart\Cpp ? ? ? ? 我们使用如下指令对 main.cpp 文件进行预处理:
? ? ? ? 上面这条指令中各参数作用如下:
? ? ? ? 进行预处理之后会得到预处理文件 main.i,位于 main.cpp 文件同级目录: ? ? ? ? 打开 main.i 文件,其中内容如下,(为了便于阅读,我删除了多余空行):
? ? ? ? 我们重点关注第七行和第十二行。第七行,预处理器在检测到 #include "math.hpp" 后,将 math.hpp 文件的文件体替换到了 main.cpp 文件内。第十二行,预处理器在检测到了宏 a 和 b 时,将其文本替换为 10 和 20。因此我们可以发现,宏会在预处理阶段被处理,宏变量会被替换,宏函数也会进行相应文本替换。此外,我们发现 math.hpp 中的注释也被删除了。 汇编代码文件? ? ? ? 预处理的下一阶段是编译阶段,为了探究生成的汇编代码,我们使用如下指令编译文件:
?? ? ? ?上面这条指令中各参数作用如下:
? ? ? ? 进行编译阶段后,我们会得到文件 main.s: ? ? ? ? 打开 main.s 文件,内容如下:
? ? ? ? 这一步得到的是汇编代码,你可以看到我是在 Windows 环境下编译的。 目标文件? ? ? ? 汇编阶段,我们利用如下指令得到目标文件 main.o:
??? ? ? 上面这条指令中各参数作用如下:
? ? ? ? 执行这一步的前提是已经生成了汇编代码文件。此时我们得到了 main.o 文件: ? ? ? ? ?main.o 二进制文件,文本编辑器中只能看到乱码: 链接? ? ? ? 我们输入如下指令尝试输出可执行文件:
? ? ? ? 很遗憾,报错了:
? ? ? ? 其原因是比较显然的,链接这一步是链接目标文件和外部库的。我们在上述的步骤中,自始至终只对 main.cpp 文件进行了编译,而其依赖项 math.hpp 并不是一个外部库文件,我们需要对其进行额外操作。由于 math.hpp 内部函数的实现在 math.cpp 中,我们需要编译?math.cpp 文件,把它转换成一个目标文件,然后链接所有目标文件。 ? ? ? ? 我们使用如下指令编译 math.cpp 文件得到目标文件 math.o:
? ? ? ? 链接所有目标文件得到可执行文件:
? ? ? ? 这样,我们就得到了最终的可执行文件 main.exe: ? ? ? ? 上面给出的编译过程复杂且文件繁多,一般来说,我们编译示例中的代码不需要那么复杂,只需要如下一条指令即可:
总结? ? ? ? 通过以上示例,我们可以了解到,C++ 代码编译过程中,会依次生成
? ? ? ? ?C++ 代码的编译过程不可谓简单,但是了解编译背后的过程和机理可以很好地帮助我们理解、程序,正如当我知道了宏定义是在预处理阶段展开时的恍然大悟。宏定义的这一特征意味着宏函数不像普通函数有对函数栈空间的压栈操作和内存需求,效率上有一定提升。 ? ? ? ? 总之,了解 C++ 编译过程必然是一次充满收获的探险。本文仅概括了 C++ 编译生成可执行文件的过程,并未涉及静态库生成,如您有类似需求请移步:C++静态库与动态库 - 吴秦 - 博客园https://www.cnblogs.com/skynet/p/3372855.html 参考
|
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 10:56:38- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |