ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

什么是编译器?

2022-09-04 11:04:00  阅读:387  来源: 互联网

标签:文件 什么 编译器 源代码 my 链接 math


什么是编译器?

Compile Errors

如果您曾经接触过编程或编码,那么您很可能听说过编译器。特别是当您尝试构建从 GitHub 获得的 C/C++ 项目时,它们会出现丑陋的链接和编译器错误。我知道看到它们很烦人,但是,它们都意味着什么。今天我将告诉你关于编译器的最基本的事情,以便你更好地理解它们错误的原因。我将尝试一些问题,例如:它们为什么存在?他们解决了什么问题?它们是如何工作的?等等

本文仅作为介绍。有比我更聪明的冠军。如果您正在寻找更高级的文章,请查看它们。 YouTuber ' 切尔诺 ’就是一个很好的例子。我从他那里学到了大部分技能和知识。

此外,我不会谈论编译器阶段,如语法或词法分析。相反,我将专注于可能对您的项目有所帮助的事情。我希望它能让你更好地理解什么是编译器。

什么是编译器?

如果我要以 ELI5 的形式解释编译器,它会是这样的:

编译器将您的代码转换为机器可以理解的语言。

编译器基本上是一个“小”程序,它将人类可读的源代码转换为 CPU 可以理解和执行的指令集。源代码可以是 C、C++、Fortran、Rust、Swift 等。机器码实际上是汇编代码。所以我们可以说,编译器创建/产生汇编代码。

Two Most Popular Compilers — Gcc and Clang (LLVM)

一些流行的编译器/工具包是:GCC、Clang、MSVC、英特尔 C/C++ 编译器。他们都有优点和缺点。例如;与其他编译器相比,英特尔的编译器非常擅长算术运算,Clang 提供比 GCC 更好的错误输出等。

它们为什么存在?

我们, 作为人类 , 用文字互相交流。另一方面,计算机使用 1 和 0。如果我们想与他们交谈(通过给出指示),我们需要一个“翻译”。这个翻译器需要将我们使用拉丁字母的单词转换成一堆 1 和 0。

这里我们介绍编译器。他们是我们需要的翻译人员。当然,我们不能只告诉编译器:“嘿,在屏幕上画一个三角形!”我们需要用更正式的语言交谈。我们称这些语言为“编程语言”,如 C++ 或 Rust。

长话短说,编译器存在的原因是我们之间的语言差异, 人类 ,和机器。

An Example C Code — Source: unplash.com Authort: Krishna Pandey

它们是如何工作的?

编译器不能只通过逐行阅读来翻译源代码。它需要一些抽象并分阶段工作。有两个主要阶段:编译和链接。它们是编译器需要做的最基本的任务。

Simplified Stages and Corresponding Files

为了解释每个“阶段”的作用,我编写了一个简单的 C++ 代码,它只需减去两个数字并将结果打印到屏幕上。有三个源文件: 主文件 , my_math.hpp 我的数学.cpp .基本上, 我的数学 文件是我的课程和定义编写的地方 主要的 是程序的入口点。被包围的文件 虚线正方形 是优化的汇编文件。别担心,我稍后会解释。

Source Code

编译

在编译阶段,整个源代码被分析、预处理、优化并转换为目标代码(s 图片中的第 1 到 4 个标签 )。这是所有“翻译”发生的阶段。当您收到编译错误时,它会发生在阶段。您可以通过简单地调用来编译 C++ 克++ , 铿锵++ 或类似的编译器。这是一个例子:

 铿锵++ main.cpp

默认情况下,编译器会“删除”中间文件并立即为您提供可执行文件。如果您想查看这些中间文件,您需要指定一些参数。

预处理

编译器做的第一件事是“处理”您使用“预处理器”标签指定的所有代码。例如, #包括, #定义, #ifndef。 编译器基本上只是查找所有符号 # 并处理它们。在您获得一个 。一世 文件。该文件仍然是人类可读的源代码。

Pre-Processed main.cpp

什么时候我们 #包括 iostream,它的所有函数和定义都将包含在我们的源代码中,因此得名 包括 .虽然我的源代码很小,但预处理后的文件要大得多。从 14 到 45762 行代码!它基本上做了一个复制粘贴。

您可以使用 -E 标签获取预处理文件:

 clang++ -E main.cpp > main.i

集会

现在我们有了最终的预处理源代码,编译器可以开始翻译了。在我们的例子中,C++ 源代码首先被翻译成汇编语言。汇编仍然是人类可读的代码。它有类似的操作 移动 , 添加 .这些操作对应不同的 CPU 指令。它们从字面上指定了 CPU 应该做什么!

Assembly Code of my_math.cpp

您可以使用 -S 标签获取汇编代码:

 clang++ -S my_math.cpp -o my_math.s

这里有趣的部分是我们的源代码只做减法,但汇编代码似乎做了更多的事情。调用许多操作,例如 字符串 , ldr ret .那些是什么?

编译器会执行这些额外的操作以进行更好的调试等。幸运的是,创造编译器的聪明人也创造了一种叫做 编译器优化 .他们分析您的来源并尝试通过减少装配操作来“优化”它。因此,使您的代码更快。

Compiler Optimizations Turned On

您可以看到它“优化”我的代码的效果如何。太疯狂了!编译器优化具有不同的级别,例如 o1 , o2 o3 . O3 是最激进的,可以生成最快和最优化的代码。您可以启用优化并使用 -O 标记指定级别:

 clang++ -S -O2 my_math.cpp -o my_math_opt.s

目标文件

你问什么是目标文件?它们就是我们之前提到的 CPU 指令。它们是使用之前的汇编代码创建的。您可以打开并尝试阅读它们,但它充满了 1 和 0。目标文件不是供我们阅读的,它们是供计算机使用的。

仅供参考:Windows 使用 .obj ** __ 作为文件扩展名而不是** .o .

每个目标文件对应一个源代码。所以我的 主文件 文件产生一个 主要的.o 文件和 我的数学.cpp 生产 my_math.o .您可以使用 -C 标签获取目标文件:

 clang++ -C main.cpp

最后,我们有两个可以被计算机读取的目标文件。但是,我们有两个不同的文件。哪一个将用于启动我们的程序?函数将如何定义 my_math.o 可用于 主要的.o ?答案在链接阶段。

链接

在链接阶段,所有目标文件都链接在一起。编译源代码时,可能有多个包含语句和外部函数调用。例如,在我们的 主文件 __ 文件中我们调用了一个函数“substract()”,该函数在 我的数学.cpp 文件。

Linking Two Object Files

现在,在编译阶段我们获得了两个目标文件。 主要的.o my_math.o .链接器的工作是链接这两个文件,以便它们可以相互“通信”。您可以将链接器视为“合并”。它基本上采用所有目标文件并将它们“合并”到一个文件中。您可以通过调用链接一个或多个文件并创建和执行:

 clang++ -C main.o my_math.o -o 输出

在链接阶段之后,我们终于获得了我们的可执行文件,名为 输出 .这是计算机可以执行的文件。在 Windows 中,它具有扩展名 。可执行程序 在 Linux 中 。出去 .可执行文件包括我们所有的代码 主文件 我的数学.cp 感谢编译器和链接器。

最后的话

当我们回顾过去时,我们了解了编译器是如何工作的,它服务于什么目的以及它们存在的原因。编译器基本上是我们人类和计算机之间的翻译器。它们帮助我们使用编程语言进行交流。使用汇编语言和许多不同的转换/翻译,它产生机器可读的目标文件。最后,它链接这些目标文件以创建单个可执行文件。之后,我们用它来运行我们漂亮的代码。

感谢您阅读我关于编译器的文章。我知道这根本不是技术解释。这更像是对编译器的高级和实用性。如果您发现任何错误或错误,请告诉我。

保重❤

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/12070/47520410

标签:文件,什么,编译器,源代码,my,链接,math
来源: https://www.cnblogs.com/amboke/p/16654518.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有