Linux :理解编译的四个阶段
目录
- 一、了解编译
- 二、认识编译的四个阶段
- (一)预处理
- (二)编译
- (三)汇编
- (四)链接
- 1.静态链接
- 2.动态链接
- 三、分步编译
- (一)创建.c文件
- (二)预处理
- (三)编译
- (四)汇编
- (五)链接
- (六)运行
- 四、合并编译
在Windows的IDE中编写代码时,我们只需要点击按钮就可以完成程序的编译,从而生成可执行文件。但在Linux中,我们需要使用指令来进行程序的编译和运行,因此也就需要来了解一下从代码到可执行文件会经历什么。我们这里以Linux中的gcc编译器为例。
一、了解编译
什么是编译?
把我们敲的代码变成可执行文件。
什么是可执行文件?
就是可以直接运行的程序文件。例如Windows中的.exe文件。
windows中如何编译?
在windows中我们使用IDE进行程序的编译和运行时仅需要鼠标点击几下就可以完成
Linux中如何编译代码?
在Linux中我们使用的gcc来编译C语言代码,使用g++来编译C++代码,这两个是不可以混用的。
我们都知道,在程序写好后,需要先进行编译,只有编译通过了,这个程序才可以尝试运行,如果编译都不能通过,谈何运行呢?
而程序的编译大致分为四部分:
- 预处理(预编译)
- 编译
- 汇编
- 链接
以上这四个阶段就是一个程序在整个编译阶段会经历的四步操作,接下来就让我们详细看一下这四步操作都在干什么。
二、认识编译的四个阶段
(一)预处理
假设此时我们写了一个名叫mian.c的程序。这是编译的第一阶段,这个阶段会做什么?
- 宏替换
- 去注释
- 引入头文件
什么是宏替换?
宏替换:将定义的宏直接用值替换掉
什么是去注释?
去注释:把文件中所写的注释去掉
什么是引入头文件?
我们在编写代码的过程中,不可避免地要使用库函数,因此会包含对应的头文件,头文件中存储的是库函数的函数声明。这一步就是把头文件中的包含的函数声明等内容复制到我们写的main.c程序中。这里需要注意,头文件中放的都是函数的声明,并不是定义,函数的定义在库中。也就是说,这里是把头文件中的函数声明搬进来了。
这个阶段执行完成后,生成的文件本质还是一个C程序,因为它只是引入了一些函数声明,去掉了注释,进行了宏的替换。所以这一步并不会发现我们程序的错误,我们把这个新生成的文件称为 main.i 文件。
(二)编译
编译阶段编译器会对main.i文件做什么?
- 语法语义纠错
- 把mian.i文件转换成汇编代码文件
首先检查main.i文件中的语法语义有没有错,有错自然就会报错了。如果没有错,就会把我们的mian.i程序解释成汇编指令mian.s文件。
经过这个阶段,mian.s文件就成为了汇编代码,不再是C代码。
(三)汇编
汇编阶段会对main.s文件做什么?
- 把汇编指令解释为二进制指令文件mian.o文件
这一步会将会汇编指令mian.s文件解释成二进制指令文件,也就是电脑能够识别的指令文件。此时的main.o文件就是二进制文件。
(四)链接
链接阶段会对main.o文件做什么?
- 链接库文件或相关文件,生成可执行文件。
生成main.o是不够的,此时的它还无法执行。因为我们在预处理阶段引入的仅仅是函数的声明,但是光有声明,没有定义,这也运行不了啊。
因此在这个阶段,会把main.o文件和存储函数定义的库文件进行链接,让我们的程序运行函数时,可以找到函数的实现。从而生成可执行程序main文件。
链接方式有两种:静态链接和动态链接,Linux中默认是动态链接。
1.静态链接
生成可执行程序时,会把函数在库中的实现搬到我们的文件中,这样所有的函数声明和函数定义都在可执行文件中了。
- 好处:运行时不需要依赖库文件,因为函数的定义和声明都被复制到我们的可执行文件中了。
- 坏处:因为我们把函数的定义复制到了可执行文件中,因此生成的可执行程序比较庞大。如果多个程序使用了相同的库函数,那么运行的时候内存中会存在大量冗余代码。
2.动态链接
如果我们的程序中调用了库函数A,动态链接会把A函数定义在库文件中的位置记录下来,保存到可执行文件中,并不会把函数的具体的实现复制过来。
当可执行程序运行时,动态库就会被加载到内存中,当可执行文件需要用到哪个函数的话,只需要根据记录在可执行文件中的位置,去内存中的动态库寻找即可。
- 好处:当多个程序都使用这个库的时候,只需要加载一个到内存中即可。这样代码冗余更小。
- 坏处:运行程序时,动态库必须存在,不然去哪里找函数的实现。
三、分步编译
- gcc -E main.c -o main.i:将main.c文件预处理成main.i文件
- gcc -S main.i -o main.s:将main.i文件编译为汇编文件main.s
- gcc -c main.s -o main.o:将main.s文件经过汇编处理,生成main.o文件
- gcc mian.o -o mian:将main.o文件与库文件链接,生成可执行文件main
(一)创建.c文件
注意:这里的-o是指定生成的文件名称。


(二)预处理
gcc -E main.c -o main.i

(三)编译
gcc -S main.i -o main.s

(四)汇编
gcc -c main.s -o main.o

(五)链接
gcc mian.o -o mian

(六)运行

四、合并编译
按照上面的分步编译虽然可以达到我们的预期目标,但是比较麻烦,毕竟敲那么多指令也比较费事,因此推荐采用下面这样的合并编译。
- gcc -E main.c -o main.i:将main.c文件处理到预处理阶段完毕
- gcc -S main.c -o main.s:将main.c文件处理到编译阶段完毕
- gcc -c main.c -o main.o:将main.c文件处理到汇编阶段完毕
- gcc mian.c -o mian:将main.c文件处理到链接阶段完毕。
上面这些指令可以提高我们的效率,因此通常直接使用第四条指令一步到位。

相关文章:
Linux :理解编译的四个阶段
目录一、了解编译二、认识编译的四个阶段(一)预处理(二)编译(三)汇编(四)链接1.静态链接2.动态链接三、分步编译(一)创建.c文件(二)预…...
197.Spark(四):Spark 案例实操,MVC方式代码编程
一、Spark 案例实操 1.数据准备 电商网站的用户行为数据,主要包含用户的 4 种行为:搜索,点击,下单,支付 样例类: 2. Top10 热门品类 先按照点击数排名,靠前的就排名高;如果点击数相同,再比较下单数;下单数再相同,就比较支付数。 我们有多种写法,越往后性能越…...
Vue 项目如何迁移小程序
最近我们看到有开发者在社群里提出新的疑惑「我手头已经有一个成熟的 HTML5 项目了,这种项目可以转为小程序在 FinClip 环境中运行吗?」。 经过工作人员的沟通了解,开发者其实是想将已有的 Vue 项目转为小程序,在集成了 FinClip …...
unit1-问候以及介绍
unit1-问候以及介绍 重点表达 1、问好 使用hello 和 hi 来打招呼。hello可以使用在正式和非正式的场合。hi是非正式的。但是hello 和 hi 都可以在一天的任何时段使用。 Hello. 你好。 Hi! 嗨! 介绍你的姓名 使用 I’m 和 My name is 告诉别人你的名字。 I’m Pau…...
杂记——19.git上传时出现the remote end hung up unexpectedly错误
git是大家常用的项目版本控制工具,熟练地使用git可以提高开发效率,但是有时在使用git推送代码时,会提示“the remote end hung up unexpectedly”的问题,那么git推送代码提示“the remote end hung up unexpectedly”怎么解决呢&a…...
python123平台题目
作业二 1. 2的n次方描述输入格式输出格式输入输出实例代码解析2. 输出最大值描述输入格式输出格式输入输出示例代码解析3. 字符串输出描述输入格式输出格式输入输出示例代码解析4. 字符串长度描述输入格式输出格式输入输出示例代码解析...
ROS学习笔记(六):TF坐标变换
ROS学习笔记(六):TF坐标变换TF的基本知识TF工具tf_monitortf_echostatic_transform_publisherview_frames创建TF广播器创建TF监听器TF的基本知识 TF是一个让用户随时间跟踪多个坐标系的功能包,它使用树形数据结构,根据…...
【python】为你绘制玫瑰一束,爱意永存
前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 若是有真情,爱意如溪水, 若是有真爱,爱意如阳光, 若是两情相悦,又岂在朝朝暮暮, 女子淡淡的情愫,深深地想念, 浓浓的爱意&a…...
智能家居创意产品一Homkit智能通断器
智能通断器,也叫开关模块,可以非常方便地接入家中原有开关、插座、灯具、电器的线路中,通过手机App或者语音即可控制电路通断,轻松实现原有家居设备的智能化改造。 随着智能家居概念的普及,越来越多的人想将自己的家改…...
【数据库】MySQL表的增删改查(基础命令详解)
写在前面 : 语法中大写字母是关键字,用[]括这的是可以省略的内容。文中截图是相对应命令执行完得到的结果截图。1.CRUD 注释:在SQL中可以使用“--空格描述”来表示注释说明.CRUD:即增加(Create)、查询(Retrieve)、更新(Update)、删除(Delete)四个单词的首…...
2023年全国最新保安员精选真题及答案15
百分百题库提供保安员考试试题、保安职业资格考试预测题、保安员考试真题、保安职业资格证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 151.该图所要表达的是()消防器材。 A:地上消防栓 B:灭火器 …...
KPN对任意形状文本检测
文章目录一、研究背景二、方法流程1. 特征提取2. 核建议3. 实例无关特征图4. 轮廓生成5. 其余部分内容三、不足一、研究背景 相比起基于 FCN 网络的文本边缘检测网络,KPN网络可以更好地处理文本之间的间隔。 二、方法流程 1. 特征提取 FCN 和 FPN FCN(全卷积神经…...
同城外卖跑腿系统源码分析
外卖订餐已经成为很多“社畜”日常不可分割的一部分,足不出户,只需要一部电子设备即可在线订餐,并且可提供的选择非常多样化,与传统的电话订餐外卖模式相比也更便捷的多。 因此,同城外卖跑腿系统源码得以爆火ÿ…...
SCL_PFENET跑通填坑
1.数据准备:VOC2012数据集,initmodel文件夹(预训练模型),SegmentationClassAug数据2.训练部分:训练部分没什么需要改动的,也就改一下选择的配置文件。在config文件夹里有关于coco和voc数据的配置…...
Redis 做延迟消息队列
背景 看到消息队列,我们肯定会想到各种MQ,比如:RabbitMQ,acivityMQ、RocketMQ、Kafka等。 但是,当我们需要使用消息中间件的时候,并非每次都需要非常专业的消息中间件,假如我们只有一个消息队…...
刚果金FERI证书模板
FERI办理流程介(一)申请资料1:FERI APPLICATION FORM申请表格;2:草本海运提单(DRAFT B/L COPY);三:已盖章的商业发飘和箱单扫描件 (Commercial Invoice&Packing list)…...
什么是蜕变测试?
文章目录1.传统测试2.蜕变测试2.1.蜕变测试的理解2.2.蜕变测试的步骤2.2.1.生成蜕变关系2.2.2.生成蜕变用例2.2.3.执行蜕变用例2.2.4.校验蜕变关系参考文献1.传统测试 在没有蜕变测试的时代,传统软件测试的原理是:给定输入,观察被测软件的输…...
74. ‘pip‘不是内部或外部命令,也不是可运行的程序-解决办法
74. pip’不是内部或外部命令,也不是可运行的程序-解决办法 文章目录74. pip不是内部或外部命令,也不是可运行的程序-解决办法1. 课题导入2. 手动配置环境变量1. 准备工作2. 配置步骤3. 命令行安装1. 课题导入 有的同学在使用pip安装第三方库时…...
MIL图像处理那些事:应用程序模块(Mapp)- 初始化和控制MIL应用程序的执行环境
提示:本系列文章通过示例详细介绍MIL图像处理的基础知识及相关操作,让给你快速学会使用MIL进行图像处理 文章目录 前言初始化Mil环境MappAllocMappAllocDefault计时MappTimer异常处理打开和关闭 Mil 异常提示C# try...catch回调函数MappHookFunction查询MappInquire文件操作Ma…...
Pytorch基础语法学习2——argparse模块
一、基本介绍 argparse 模块是 Python 内置的用于命令行参数解析的模块,可以通过少数代码中变量或者参数的改变以实现对整个代码项目的操控。对于大型代码项目(如代码超过1000行),十分便捷 argparse 模块可以让人轻松编写用户友好的命令行接口…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
