【Linux】程序的翻译四个阶段(图示详解)

news2025/1/8 17:57:23

因为淋过雨,所以懂的为别人撑伞;因为迷茫过,所以懂得为别人指路。

 我们都知道写好代码后,编译器会帮助我们把代码生成可执行程序,细加了解又会知道程序的生成又分为四步:预处理、编译、汇编、链接。那么这四步具体都在干什么?

本文目录

程序翻译之四个步骤

预处理阶段(进行宏替换等)

编译阶段(生成汇编)

 汇编(生成机器可识别代码)

链接(生成可执行文件或库文件)


程序翻译之四个步骤

我们本文以C语言讲解:

在程序生成过程中每一个C语言源文件都会通过编译过程,分别转化为目标文件(.obj),这些目标为文件会由链接器捆绑在一起,形成一个单一完整的整体,链接器同时也会引入标准C函数库中任何被该程序所用到的函数,且可以搜索程序员个人的程序库,将其需要的函数也链接到程序中,形成可执行程序。

思维导图:

程序的翻译过程

 注:Linux命令中加-o,指定输出文件名(自定义),该文件为可执行文件,不加-o会默认生成a.out。 gcc/g++是一个编译器

预处理阶段(进行宏替换等)

预处理阶段是在正式的编译阶段之前进行。预处理是C语言的一个重要的功能,它由预处理程序单独完成,当对一个源文件进行编译时,系统自动引用预处理程序,预处理在源代码编译之前根据内置预处理指令对其进行的一些文本性质的操作,对源程序编译之前做一些处理,生成扩展的C源程序(本质还是C语言代码)

  1. 头文件包含:如#include "FileName"或者#include 等。 该指令将头文件中的定义统统都加入到它所产生的输出文件中,以供编译程序对之进行处理。
  2. 宏替换:如 #define a b 对于这种伪指令,预编译所要做的是将程序中的所有a用b替换,但作为字符串常量的 a则不被替换。还有 #undef,则将取消对某个宏的定义,使以后该串的出现不再被替换。
  3. 去注释:删除源代码中掉注释的过程,注释不会被带入到编译阶段
  4. 条件编译:如#ifdef,#ifndef,#else,#elif,#endif等。 这些伪指令的引入使得程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。预编译程序将根据有关的文件,将那些不必要的代码过滤掉

图示: 

源代码
查看详细信息

 可以看到在进行了预处理之后生成.i文件后,文件体积变大了很多,代码由几行变成了八百多行,并且进行了宏替换,去注释等操作。

预处理程序对源程序进行上述“文本替换工作”后,输出的文件(还是C语言代码)中将不再包含宏定义、文件包含、条件编译等指令,源文件相比功能相同,形式不一样。

编译阶段(生成汇编)

编译阶段,gcc会将C语言代码转换成汇编代码文件(.s)。在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。

图示:

 我们可以看到在执行命令后我们生成了一个汇编文件,将C语言源代码转化成了汇编代码

 汇编(生成机器可识别代码)

汇编过程是将汇编语言代码翻译生成目标文件(.obj)-二进制文件的过程。目标文件由机器码组成。通常它至少有代码段和数据段两部分。前者包含程序指令,后者存放程序中用到的各种全局/静态数据。

图示:

在这里可以看到,生成的文件是二进制文件,显示一片乱码我们完全看不明白。这是因为汇编过程还会生成一个符号表,因为这个二进制文件是elf格式的,我们可以通过Linux的readelf工具来阅读二进制文件:

汇编阶段生成了可重复定位目标二进制文件,此文件是不可以被执行的同时通过符号表打印件我们可以看到,一个类似表格的东西,里面有main,printf等符号,这个就是生成的符号表 :在符号表中,程序源代码中的每个标识符都和它的声明或使用信息绑定在一起,比如其数据类型、作用域以及内存地址。

链接(生成可执行文件或库文件)

链接阶段将我们生成的.obj文件和库文件某种合并,生成可执行程序。链接程序要解决外部符号访问地址问题,就是将一个文件中引用的符号与该符号在另一个文件中的定义连接起来,从而使有关的目标文件连成一个整体,最终成为可被操作系统执行的可执行文件。

在这里涉及到一个重要的概念 : 函数库
我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?
最后的答案是 : 系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了 , 在没有特别指定时 ,gcc 会到系统默认的搜索路径“/usr/lib” 下进行查找 , 也就是链接到 libc.so.6 库函数中去 , 这样就能实现函数“printf” , 而这也就是链接的作用。

当你们在安装VS2019、VS2022的时候,实际上最重要的一个工作是什么呢?就是帮我们下载并安装语言的头文件和库文件! 

其实我们用的Linux指令(命令),有相当一部分就是用C写的!如何看到指令呢?通过linux命令:ldd命令(用于打印程序或者库文件所依赖的共享库列表)可以查看,指令就是程序。

函数库一般分为静态库和动态库两种:
  • 静态库:指编译链接时,把静态库文件中我们所需要的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”
  • 动态库:指编译链接时,拷贝动态库中我们所需要的代码的地址到我们可执行文件中的相关位置,在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件。
  • 优缺点:
  • 静态库:链接成功后,我们的程序不依赖任何库,自己可以独立运行;但是因为自身拷贝问题,比较浪费内存空间
  • 动态库:链接成功后,我们的程序还是依赖动态库(共享),程序内部只有地址,比较节省内存空间;但是一旦动态库缺失,我们的程序将无法运行!
  • 对于Linux: 静态库 vs 动态库,Linux中默认使用的事动态链接和动态库!

 本节完


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

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

相关文章

JAVA语言基础语法——异常中的常见方法及抛出异常等练习

Throwable的成员方法定义在最顶级Throwable类中a.实例如下:e.printStackTrace(); 将异常的所有信息红色的字体打印在控制台,不会结束虚拟机,仅仅只是打印的操作。抛出处理throws注意:写在方法定义处,表示声明一个异常&…

DOM(三):鼠标、键盘事件对象

鼠标、键盘事件对象鼠标事件对象键盘事件对象鼠标事件对象 event对象代表事件的状态,和事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象MouseEvent和键盘事件对象KeyboardEvent 例如: // 鼠标事件对象 MouseEventdocument.addEventListene…

Android正确的保活方案,不要掉进保活需求死循环陷进

在开始前,还是给大家简单介绍一下,以前出现过的一些黑科技: 大概在6年前Github中出现过一个叫MarsDaemon,这个库通过双进程守护的方式实现保活,一时间风头无两。好景不长,进入 Android 8.0时代之后&#x…

STM32系列单片机标准库移植FreeRTOS V10.4.6详解

文中所用到的资料下载地址 https://download.csdn.net/download/qq_20222919/87370679 最近看正点原子新录制了手把手教你学FreeRTOS的视频教程,看了一下教程发现视频里面讲的是使用HAL移植 FreeRTOS V10.4.6 版本,以前的标准库移植的是FreeRTOS V9.0 版…

关于PostgreSQL JIT Memory-Leak 问题 从 LLVM源码层面来分析

文章目录前言LLVM Types 在 JIT中的使用LLVM Types 设计导致的 PG JIT 内存问题分析解决?前言 之前介绍 PG 的 JIT 实现 时提到 为了性能开启JIT 之后有一个比较严重的内存泄漏问题。现象就是在一个backend 内持续跑大量的 sqllogic 随机复杂查询,能够看…

java 微服务 Nacos配置 feign 网关路由

Nacos配置管理 配置信息我们写有热更新需求的配置就可以了 1.引入Nacos的配置管理客户端依赖&#xff1a; <!--nacos配置管理依赖--> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config…

HBase基础_1

HBase 注&#xff1a;大家觉得博客好的话&#xff0c;别忘了点赞收藏呀&#xff0c;本人每周都会更新关于人工智能和大数据相关的内容&#xff0c;内容多为原创&#xff0c;Python Java Scala SQL 代码&#xff0c;CV NLP 推荐系统等&#xff0c;Spark Flink Kafka Hbase Hive…

学习笔记6:字符串库函数(下)

目录 一. strstr模拟实现 二. strtok模拟实现 三.关于strerror和perror的说明 一. strstr模拟实现 库函数strstr函数首部&#xff1a;char * strstr ( const char *str1, const char * str2); 函数的功能是在str1指向的主字符串中寻找子串str2&#xff0c;并且返回主字符串中…

JS数组对象——英文按照首字母进行排序sort()、localeCompare()

JS数组对象——英文按照首字母进行排序(sort、localeCompare&#xff09;上期回顾场景复现sort()方法与localeCompare实例应用上期回顾 文章内容文章链接JS数组对象——根据日期进行排序Date.parse()&#xff0c;按照时间进行升序或降序排序https://blog.csdn.net/XSL_HR/arti…

【CANN训练营第三季】AI目标属性编辑应用

文章目录1、参考样例进行运行stargan2、dvpp媒体数据处理结业考核题目1、题目2、题目31、参考样例进行运行stargan 下载stargan后&#xff0c;查看readme&#xff0c;进行复现。 # 为了方便下载&#xff0c;在这里直接给出原始模型下载及模型转换命令,可以直接拷贝执行。 cd …

Tic-Tac-Toe:基于Minimax算法的人机对弈程序(python实现)

目录 1. 前言 2. Minimax算法介绍 2.1 博弈树 2.2 估值函数 2.3 基本算法思想 2.4 实例1 ​​​​​​​2.5 实例2—棋类游戏 2.6 小结 3. Tic-Tac-Toe minimax AI实现 3.1 函数说明 3.2 处理流程 3.3 代码 4. 小结 1. 前言 在上一篇中实现一个简单的Tic-Tac-Toe人…

【07】概率图推断之信念传播

概率图推断之信念传播 文章目录将变量消除视为信息传递信息传递算法加总乘积信息传递因子树上的加总乘积信息传递最大乘积信息传递总结在《概率图推断之变量消除算法》中&#xff0c;我们讲了变量消除算法如何对有向图和无向图求P(Y∣Ee)P(Y \mid E e)P(Y∣Ee)的边缘概率。 …

java 微服务之MQ 异步通信

初识MQ 同步调用存在的问题 异步调用常见实现就是事件驱动模式 事件驱动模式优势&#xff1a; 优势1&#xff1a;服务解耦 一旦有新业务只需要订阅或者减少事件就行了 优势2&#xff1a;性能提升&#xff0c;吞吐量提高 优势3&#xff1a;服务没有强依赖&#xff0c;不用担…

【自学C++】C++注释

C注释 C注释教程 用于注解说明解释程序的文字就是注释&#xff0c;注释提高了代码的阅读性。同时&#xff0c;注释也是一个程序员必须要具有的良好编程习惯。我们应该首先将自己的思想通过注释先整理出来&#xff0c;再用代码去体现。 在 C 中&#xff0c;一旦程序中某部分内…

数据结构和算法-计数排序

1.算法描述 技术排序是一个基于比较的排序算法&#xff0c;该算法于1954由Harold H. Seward 提出。它的优势在于对 一定范围内的整数排序时&#xff0c;它的复杂度为O&#xff08;nk&#xff09;&#xff08;其中k是整数的范围&#xff09;&#xff0c;快于任何比较排序算 法…

JavaEE高阶---Spring事务和事务传播机制

一&#xff1a;什么是事务&#xff1f; 事务定义&#xff1a;将⼀组操作封装成⼀个执⾏单元&#xff08;封装到⼀起&#xff09;&#xff0c;要么全部成功&#xff0c;要么全部失败。 二&#xff1a;Spring中事务的实现 编程式事务&#xff08;⼿动写代码操作事务&#xff09…

使用 Flink CDC 实现 MySQL 数据实时入 Apache Doris

简介 主要内容如下&#xff1a; MySQL 安装和开启binogFlink环境准备Apache Doris 环境准备启动Flink CDC作业 1. MySQL 安装和开启binog 参考文章&#xff1a;Ubuntu 安装 Mysql server, 这篇文章介绍了MySQL的安装&#xff0c;用户创建&#xff0c;Binlog开启等内容。 M…

Linux基础入门和常用命令

Linux基础入门和常用命令一. Linux介绍1.1 Linux的发行版本二. Linux环境搭建三. Linux的常用指令3.1 Linux下的目录结构3.2 ls命令3.3 pwd命令3.4 cd指令3.5 touch指令3.6 mkdir指令3.7 rmdir指令和 rm 指令3.8 man指令3.9 mv指令3.10 cp指令3.11 cat3.12 more指令3.13 less指…

基于机器学习组合模型的个人信用评估

《基于机器学习组合模型的个人信用评估》课程报告 摘要 个人信用评估在信用经济市场发挥着及其重要的基础作用&#xff0c;促进信用经济的发展&#xff0c;稳定经济市场。个人信用信息主要有个人基本信息、还款能力和还款意愿;个人基本信息主要由年龄、性别、地区等特征构成&…

C语言灵魂核心——指针深度修炼

&#x1f412;个人主页&#xff1a;平凡的小苏&#x1f4da;学习格言&#xff1a;别人可以拷贝我的模式&#xff0c;但不能拷贝我不断往前的激情目录 1. 字符指针 2. 指针数组 3. 数组指针 3.1 数组指针的定义 3.2 &数组名VS数组名 3.3 数组指针的使用 4. 数组参数、…