【Linux】程序的翻译过程(图示详解)

news2025/1/16 18:41:00

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

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

本文目录

程序翻译之四个步骤

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

编译阶段(生成汇编)

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

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


程序翻译之四个步骤

我们本文以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/145119.html

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

相关文章

STM32MP157驱动开发——Linux IIO驱动(上)

STM32MP157驱动开发——Linux IIO驱动(上 )0.前言一、IIO 子系统简介1.iio_dev 结构体2.iio_dev 申请与释放3.iio_dev 注册与注销4.iio_info5.iio_chan_spec二、驱动开发1. ICM20608 的 IIO 驱动框架搭建2.IIO 设备申请与初始化3.基于以上驱动框架开发 I…

[JavaEE初阶] 线程安全问题的原因和解决方案

努力努力,月薪过亿!!! 格局打开~~~ 文章目录前言1. 线程安全问题的概念2. 线程安全问题的原因3. 线程安全问题解决--加锁3. synchronized4. 死锁4.1 产生死锁的情况4.3 产生死锁的必要条件4.4 避免死锁的方法前言 线程安全这里可能会出道面试题,在日常工作中也是很重要的内容.…

MathType公式对齐不正确

MathType公式对齐不正确1.软件环境⚙️2.问题描述🔍3.解决方法🐡4.1.通过标尺对齐4.2.通过输入具体的制表符位置对齐1.软件环境⚙️ Windows10 教育版64位 Word 2021 MathType 7 2.问题描述🔍 在使用Word写论文的时候,总是避免不…

JavaScript 模块:理解模块系统

前言 现代JavaScript开发毋庸置疑会遇到代码量大和广泛使用第三方库的问题。解决这个问题的方案通常需要把代码拆分成很多部分,然后再通过某种方式将它们连接起来。 在ECMAScript 6模块规范出现之前,虽然浏览器原生不支持模块的行为, 但也迫…

ssh连接ubuntu报错

记录问题:1我在本机windows用ssh rootubuntu连接失败 显示端口21啥的2 打开Ubuntu系统,输入ps -e|grep ssh,发现只有agent,没有server3 安装ssh server,输入sudo apt-get install openssh-server,发现报错信…

仅需一个注解,实现 SpringBoot 项目中的隐私数据脱敏!

这两天在整改等保测出的问题,里面有一个“用户信息泄露”的风险项(就是后台系统里用户的一些隐私数据直接明文显示了),其实指的就是要做数据脱敏。数据脱敏:把系统里的一些敏感数据进行加密处理后再返回,达…

一键自动化 | Salesforce发布Automation Anywhere自动化组合!

2022年12月1日,Salesforce推出了一个新的Automation Everywhere Bundle,以加速端到端的工作流编排(Workflow Orchestration)、跨系统自动化,以及在任何地方嵌入数据和AI驱动的工作流。 该捆绑包完全集成到Salesforce F…

acwing第84场周赛(4788,4789,4890)题解

4788. 最大数量 某商场在一天中一共来了 nn 个客人。 每个客人进入商场的具体时刻(精确到分钟)已知。 请你计算并输出在同一时刻(精确到分钟)进入商场的最大客人数量。 输入格式 第一行包含整数 nn。 接下来 nn 行&#xff…

二叉搜索树比起二叉树又有什么不一样呢?

二叉搜索树比起二叉树又有什么不一样呢?🏐什么是二叉搜索树🏐二叉搜索树的实现🏀节点类:🏀构造函数🏀析构函数🏀插入insert⚽非递归版本⚽递归版本🏀查找find⚽非递归版本⚽递归版本…

spring boot 八:SpringBoot响应返回xml数据

spring boot 八&#xff1a;SpringBoot响应返回xml数据 1 前言 根据DispatcherServlet源码分析&#xff0c;研究SpringBoot的Controller返回xml数据的一些方法&#xff0c;包含单独配置和全局配置返回xml数据两种方式。 依赖的SpringBoot版本&#xff1a; <parent>&l…

u盘有病毒怎么办?修复U盘,3个方法解决

U盘和外部的驱动器相比&#xff0c;它的体积更小&#xff0c;携带更加方便&#xff0c;可以轻松地与他人分享文件。虽然U盘使用很方便&#xff0c;但是有时会出现中病毒的情况。u盘有病毒怎么办&#xff1f;如果您也受到此问题的影响&#xff0c;我们可以提供一种有效的方法来修…

物联网架构实例—Ubuntu 安装Redis

1.准备更新apt-get源sudo apt-get update2.安装执行Redis 安装命令sudo apt-get install redis-server3.检查安装状态sudo /etc/init.d/redis-server status查看Redis运行进程ps -aux|grep redis4.将Redis添加到服务器启动项修改/etc/rc.localvim /etc/rc.local将下面的命令加到…

阿里云办公安全产品专家高传贵:零信任,让全球办公安全更简单

2022 年 8 月 30 日&#xff0c;阿里云用户组&#xff08;AUG&#xff09;第 9 期活动在北京举办。活动现场&#xff0c;阿里云办公安全产品专家高传贵&#xff0c;向参会企业代表分享了零信任&#xff0c;让全球办公安全更简单。本文根据演讲内容整理而成。 大家下午好。我今天…

内部类导致的内存泄漏

前两天刷文章偶然翻到一篇因使用非静态内部类时导致内存泄漏的问题,出于好奇自己也动手一试 什么叫内存泄漏 内存泄漏&#xff08;Memory Leak&#xff09;是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放&#xff0c;造成系统内存的浪费&#xff0c;导致程序…

WuThreat首个发布全球领先的身份安全云产品ITDR Cloud

随着数字化、人工智能&#xff0c;公有/私有云&#xff0c;物联网络及5G等技术的全面普及和迭代更新&#xff0c;身份管理建设作为企业重要的基础设施。然而现在黑客攻击手段复杂多样&#xff0c;在历年的实战攻防演习中有大量的应用系统与基础设施的的身份入口被攻破&#xff…

【从零开始学习深度学习】38. Pytorch实战案例:梯度下降、随机梯度下降、小批量随机梯度下降3种优化算法对比【含数据集与源码】

本文将使用一个来自NASA测试不同飞机机翼噪音的数据集&#xff0c;通过梯度下降、随机梯度下降、小批量随机梯度下降这3种优化算法进行模型训练&#xff0c;比较3种训练结果的差异。 目录1. 梯度下降、随机梯度下降、小批量随机梯度下降区别2. 读取训练数据3. 从零实现3种梯度算…

多线程与高并发(16)——线程池原理(ThreadPoolExecutor源码)

本文从ThreadPoolExecutor源码来理解线程池原理。 ThreadPoolExecutor使用了AQS、位操作、CAS操作等。在看这篇文章之前&#xff0c;需要具备以下知识&#xff1a; 多线程与高并发&#xff08;6&#xff09;——CAS详解&#xff08;包含ABA问题&#xff09; 多线程与高并发&…

腾讯三面:进程写文件过程中,进程崩溃了,文件数据会丢吗?

进程写文件&#xff08;使用缓冲 IO&#xff09;过程中&#xff0c;写一半的时候&#xff0c;进程发生了崩溃&#xff0c;会丢失数据吗&#xff1f; 答案&#xff0c;是不会的。 因为进程在执行 write &#xff08;使用缓冲 IO&#xff09;系统调用的时候&#xff0c;实际上是…

企业宣传片制作配音,我们该从哪里找?

优秀的品质的配音是制作优质企业视频必不可少的硬件条件。因此&#xff0c;许多公司视频配音或旁白声音是由专门从事配音行业的人员配音的。 首先是在宣传视频中配音的作用 1.宣传视频的配音为您建立企业形象 2.宣传视频的配音将为您打开市场 3.宣传视频的配音将使您的宣传…

深入理解Synchronized

Synchronized 底层原理 Synchronized的语义底层是通过一个 Monitor 的对象来完成&#xff0c;其实wait/notify等方法也依赖于 Monitor 对象&#xff0c;这就是为什么只有在同步的块中&#xff0c;拿到锁之后&#xff0c;才能调用wait/notify等方法&#xff0c;否则会抛出java.…