Linux的编译器

程序编译的过程

程序的编译过程是将源代码转换为可执行文件的一系列步骤。这个过程涉及多个阶段,主要包括预处理、编译、汇编和链接。下面详细介绍每个阶段:

1. 预处理(Preprocessing)

在实际编译之前,源代码文件首先经过预处理器处理。预处理阶段主要处理那些以井号(#)开头的指令,如宏定义(#define)、文件包含(#include)等。预处理器执行的任务包括:

  • 宏展开:将所有的宏定义替换为相应的值。
  • 文件包含:将包含指令(#include)指定的文件内容插入到源代码文件中。
  • 条件编译:根据特定的条件编译指令,决定是否编译代码的特定部分。
  • 移除注释:从源代码中移除所有注释。

2. 编译(Compilation)

预处理后的代码(现在是纯文本)被送到编译器,编译器将其转换成汇编代码。编译阶段的主要任务是:

  • 语法分析:检查代码是否符合语言的语法规则。
  • 语义分析:检查代码中的表达式和语句是否有意义(比如类型检查)。
  • 生成中间代码:生成一种更接近机器语言的中间表示形式,通常是汇编语言。

3. 汇编(Assembly)

汇编器接收编译阶段生成的汇编代码,将其转换为机器码(二进制代码)。每一条汇编指令几乎直接对应一条机器指令。生成的输出通常是目标文件(.o 或 .obj 文件),这些文件包含了程序的机器语言表示。

4. 链接(Linking)

程序通常由多个源代码文件组成,这些文件需要被单独编译和汇编。链接器的任务是将一个或多个目标文件合并成一个单一的可执行文件。在链接过程中,链接器还会解决程序中各个部分之间的引用和依赖问题,例如:

  • 解析外部引用:处理程序不同部分或外部库之间的调用关系。
  • 地址绑定:确定程序和数据在内存中的位置。
  • 库链接:将程序需要的库(动态链接库或静态库)合并到最终的可执行文件中。

完整的流程图

源代码 -> [预处理] -> 预处理后的代码 -> [编译] -> 汇编代码 -> [汇编] -> 目标代码 -> [链接] -> 可执行文件

这个过程是高度自动化的,通常由构建系统(如 Makefiles、CMake 等)控制,它会根据需要执行上述所有步骤,生成最终的可执行程序。每个阶段都有专门的工具和软件来执行,比如 GCC 或 Clang(在 C/C++ 开发中)等。

语言自举的过程

语言自举(Bootstrapping a language)是一种使用编程语言的编译器或解释器来编写该语言本身的编译器或解释器的过程。简而言之,这意味着用一种语言编写该语言自身的编译器或解释器。这个过程中,该语言的初期版本通常是用另一种语言编写的,而后续版本则可能完全或部分使用该语言自身来进行重写或优化。

自举过程的步骤

  1. 初始实现:在最开始,编程语言的编译器或解释器通常用另一种已存在的语言编写。这样做是因为初始的编程语言还没有足够的工具和支持来自我编译。

  2. 自我编译:当这种新语言发展到足够成熟,可以支持更复杂的功能时,开发者会使用这种语言自身来重写其编译器或解释器。这意味着新语言现在可以编译自己的编译器,这通常被看作是一种成熟的标志。

  3. 优化和扩展:一旦编译器可以用其自身的语言成功编译,开发者就可以继续使用该语言来优化和扩展编译器的功能。这可能包括添加新的语言特性、优化性能或改进错误处理。

  4. 迭代改进:随着时间的推移,编译器可以不断通过自身来进行迭代改进和更新,这增强了其功能和效率,并可以支持新的编程范式或标准。

自举的优势

  • 独立性:自举减少了对其他编程语言的依赖,使得编程语言及其工具链更加独立。
  • 演示能力:使用一种语言编写其自身的编译器是对该语言功能强大和成熟度的展示。
  • 自我验证:自举过程可以作为一种验证手段,证明语言足够强大,能够处理复杂的编程任务,如编写和处理编译器代码。

自举的例子

  • C语言:C语言最初的编译器是用汇编语言编写的,但很快之后,C的编译器就开始用C语言本身来编写,这是最著名的自举案例之一。
  • Pascal:Niklaus Wirth 设计的 Pascal 语言也是先用其他语言编写了编译器,后来用 Pascal 自身重写。
  • Rust:Rust 语言最初的编译器是用 OCaml 编写的,现在的 Rust 编译器(rustc)主要用 Rust 本身编写。

gcc / g++

GCC(GNU Compiler Collection)是一个开源的编译器套件,支持多种编程语言,其中最为人熟知的是 C 和 C++(通过 G++ 编译器)。GCC 是在自由软件基金会(FSF)的 GNU 项目下开发的,旨在提供一个标准的、高性能、高可靠性的编译器,它在开源和自由软件开发中占有非常重要的地位。

  1. 多语言支持:GCC 最初是作为一个 C 语言编译器开始的,但后来扩展到支持多种语言,包括 C++(G++)、Objective-C、Fortran、Ada、Go,以及 Java 等。

  2. 跨平台:GCC 可以在多种类型的操作系统上运行,包括 Linux、Mac OS、Windows(通常通过 MinGW 或 Cygwin)等,支持广泛的架构,如 x86、x64、ARM、PowerPC 等。

  3. 代码优化:GCC 提供了多种级别的优化选项,可以帮助开发者提高程序的执行效率。从 -O0(无优化)到 -O3(最大优化),还有 -Os(优化空间)和 -Ofast(忽略严格标准的最快速优化)。

  4. 标准遵从:GCC 高度遵循各个编程语言的标准,如 ISO C、C++,并定期更新以支持最新的语言标准。

  5. 调试和错误报告:GCC 提供详细的错误和警告消息,帮助开发者诊断代码问题。配合 GDB(GNU Debugger)使用,可以有效地进行代码调试。

  6. 扩展性:GCC 也支持内联汇编,允许开发者插入架构特定的汇编代码来优化程序,同时支持自定义的编译器插件。

G++ 是 GCC 中的 C++ 编译器,支持 C++ 的所有标准特性,包括最新的 C++20 标准。G++ 不仅能够编译复杂的 C++ 应用程序和库,还支持异常处理、模板编程等现代 C++ 特性。

动态库&&静态库

静态库和动态库是在软件开发中用来实现代码重用和模块化的两种不同类型的库。它们主要的区别在于它们如何被集成和使用在应用程序中。

静态库

静态库是一种在程序编译时期就已经被包含进程序的库。它们通常包含一组编译好的代码,这些代码可以直接链接到最终的可执行文件中。

  • 集成方式:在编译阶段,静态库中的代码被复制到最终的可执行文件中。这个过程是由链接器完成的,链接器将程序中用到的静态库中的对象文件直接集成到程序的可执行文件中。
  • 部署和分发:由于静态库的内容已经被集成到可执行文件中,所以这些程序在分发时不需要附带这些库文件。可执行文件本身就包含了所有必要的代码。

动态库

动态库是一种在程序运行时才加载的库。它们的代码在程序运行时被载入内存,并通过操作系统进行管理。

  • 集成方式:动态库并不是在编译时被包含进可执行文件,而是在程序运行时由操作系统动态地加载。程序在运行时会请求操作系统加载所需的库,并将其链接到正在运行的程序中。
  • 部署和分发:因为动态库不是程序的一部分,所以在分发这些程序时,需要确保动态库可以在目标系统上被访问。通常,动态库需要与程序一起分发,或者确保目标系统已经安装了相应的库。

区别

  • 链接时期:静态库在编译时被集成,动态库在运行时被加载。
  • 体积影响:使用静态库的程序通常体积更大,因为所有需要的库代码都被包含在内;使用动态库的程序体积更小,但需要在运行环境中有对应的库。
  • 运行依赖:静态库的程序运行时不依赖外部库文件,而动态库的程序需要在运行时环境中访问这些库。
  • 更新和维护:动态库更易于更新和维护,因为只需替换单个库文件即可影响所有使用该库的程序;静态库的更新需要重新编译和分发整个程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/8688.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android bootchart 分析启动性能工具使用

bootchart简介 bootchart 可为整个系统提供所有进程的 CPU 和 I/O 负载细分。该工具不需要重建系统映像,可以用作进入 systrace 之前的快速健全性检查。 1. 板端配置: 在Android 板端启用 bootchart,请运行以下命令: 2. Bootch…

Git克隆仓库报错:HTTP/2 stream 1 was not closed

报错及原因 fatal: unable to access ‘https://github.com/xxx/’: HTTP/2 stream 1 was not closed cleanly before end of the underlying stream http/2 和 http/1.1之间有个区别是“HTTP2 基于 SPDY,专注于性能,最大的一个目标是在用户和网站间只…

PMP考试未通过该怎么办?如何补考?

2024年3月10日PMP考试成绩正在陆续分批次发布。没有考试通过的同学就会疑问,考试没考过怎么办?可不可以补考?面对PMP考试没通过的情况,我们应该如何应对呢? PMP考试没合格可以补考,而且一年内有两次补考机…

编译官方原版的openwrt并加入第三方软件包

最近又重新编译了最新的官方原版openwrt-2305(2024.3.22),此处记录一下以待日后参考。 目录 1.源码下载 1.1 通过官网直接下载 1.2 映射github加速下载 1.2.1 使用github账号fork源码 1.2.2 创建gitee账号映射github openwrt 2.编译准…

ChatGPT DALL-E绘图,制作各种表情包,实现穿衣风格的自由切换

DALL-E绘图功能探索: 1、保持人物形象一致,适配更多的表情、动作 2、改变穿衣风格 3、小女孩的不同年龄段展示 4、不同社交平台的个性头像创作 如果不会写代码,可以问GPT。使用地址:我的GPT4 视频,B站会发&#…

【YOLO改进】换遍MMDET主干网络之MobileNetv2(基于MMYOLO)

MobileNetv2 MobileNetV2是一种专为移动和嵌入式视觉应用设计的轻量化网络结构。它在MobileNetV1的基础上引入了两个主要的创新点:反转残差结构(Inverted Residuals)和线性瓶颈层(Linear Bottlenecks)。 反转残差结构…

Linux fsck.ext2命令教程:如何检查和修复ext2文件系统(附实例详解和注意事项)

Linux fsck.ext2命令介绍 fsck.ext2是一个用于检查和(可选)修复Linux ext2/ext3/ext4文件系统的命令。当ext2文件系统发生错误时,可以使用fsck.ext2命令尝试进行修复。 Linux fsck.ext2命令适用的Linux版本 fsck.ext2命令在大多数Linux发行…

yolov8任务之目标检测

对象检测 对象检测是一项涉及识别图像或视频流中对象的位置和类别的任务。对象检测器的输出是一组包围图像中对象的边界框,以及每个框的类标签和置信度分数。当您需要识别场景中感兴趣的对象,但不需要确切知道对象在哪里或其确切形状时,对象检…

我独自升级崛起账号注册 我独自升级怎么注册账号

近期,《我独自升级》这部动画凭借爆棚的人气,在各大平台上掀起了一阵观看热潮,其影响力不容小觑。借此时机,韩国游戏巨头网石集团敏捷响应,顺势推出了同名游戏《我独自升级:ARISE》,为粉丝们搭建…

SLAM种的回环检测

SLAM,即同步定位与建图,是一种在未知环境中,通过传感器(如相机、激光雷达等)进行自身定位与环境地图构建的技术。其中,回环检测是SLAM中的一个重要环节。 回环检测的主要目的是识别机器人是否回到了之前访…

webpack配置、插件使用案例

概念 本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles&…

关闭vscode保存自动格式化的功能

1 首先打开设置 搜索:editor.formatOnSave 取消勾选框 2 再打开 settings.json 搜索 editor 找到 settings.json 设置: "editor.formatOnSave": false

Java并发控制:深入解析Java BlockingQueue的用法与实践

1.BlockingQueue概述 1.1 BlockingQueue的定义与用途 BlockingQueue是一个支持两个附加操作的Queue,即在队列为空时获取元素的线程会等待队列变为非空,当队列满时存储元素的线程会等待队列可用。这主要用于生产者-消费者场景,其中生产者不能…

算法day02

1、202. 快乐数 如上题所述: 在该题意规则下,所有的数字变化会有两种情况,其一最后是有的会变化成恒为1的数;其二是有的数会变化会呈现成有规律的环,分别如下图所示: 可以近似的理解为图一就是一个环&#…

态、势、感、知四部分的注意力模型的融合

态、势、感、知在抢占注意力时往往是通过自身具有吸引力、引发情感共鸣或启发思考等方式来引起人们的注意和关注。态、势、感、知在抢占注意力方面的作用可以分别描述如下: 态:人们通常会被某种特定的姿态或面部表情所吸引,因为姿态能够传达出…

JVM堆内存分析

jmap工具查看堆内存 jmap:全称JVM Memory Map 是一个可以输出所有内存中对象的工具,可以将JVM中的heap(堆),以二进制输出成文本,打印出Java进程对应的内存 找到pid jmap -heap 19792 Attaching to process ID 19792…

(十五)Java 之方法

目录 一. 前言 二. Java 方法 2.1. 什么是方法 2.2. 方法的定义 2.3. 方法的调用 2.4. void 关键字 2.5. 通过值传递参数 2.6. 方法的重载 2.7. 变量作用域 2.8. 命令行参数的使用 2.9. 构造方法 2.10. 可变参数 2.11. finalize() 方法 三. 课后习题 一. 前言 方…

[Redis] 使用布隆过滤器和分布式锁实现用户注册

布隆过滤器(Bloom Filter)是一种数据结构,用于快速判断一个元素是否可能存在于一个集合中。它通过使用多个哈希函数和一个位数组来表示一个集合,当一个元素被加入到集合时,通过哈希函数计算出多个哈希值,并…

windows10鼠标右键添加idea打开文件

在Windows系统中,你可以通过修改注册表来为鼠标右键菜单添加新的打开方式,比如IDEA。以下是具体的操作步骤: 打开注册表编辑器:按下WinR键,输入regedit并回车,即可打开注册表编辑器。定位到指定路径&#…

怎么清理服务器的C盘?

有时候我们经常会遇到C盘被占满的情况,C盘被占满的原因有很多,下面我们就来分析下有可能导致C盘占满的原因: 第一种情况:中毒 打开服务器任务管理器选择进程,并且勾选显示所有用户的进程,我们可以点击映像…