当前位置: 首页 > news >正文

Linux :理解编译的四个阶段

目录

  • 一、了解编译
  • 二、认识编译的四个阶段
    • (一)预处理
    • (二)编译
    • (三)汇编
    • (四)链接
      • 1.静态链接
      • 2.动态链接
  • 三、分步编译
    • (一)创建.c文件
    • (二)预处理
    • (三)编译
    • (四)汇编
    • (五)链接
    • (六)运行
  • 四、合并编译

  在Windows的IDE中编写代码时,我们只需要点击按钮就可以完成程序的编译,从而生成可执行文件。但在Linux中,我们需要使用指令来进行程序的编译和运行,因此也就需要来了解一下从代码到可执行文件会经历什么。我们这里以Linux中的gcc编译器为例。

一、了解编译

 什么是编译?

把我们敲的代码变成可执行文件。

 什么是可执行文件?

就是可以直接运行的程序文件。例如Windows中的.exe文件。

 windows中如何编译?

在windows中我们使用IDE进行程序的编译和运行时仅需要鼠标点击几下就可以完成

 Linux中如何编译代码?

在Linux中我们使用的gcc来编译C语言代码,使用g++来编译C++代码,这两个是不可以混用的。

  我们都知道,在程序写好后,需要先进行编译,只有编译通过了,这个程序才可以尝试运行,如果编译都不能通过,谈何运行呢?

  而程序的编译大致分为四部分:

  • 预处理(预编译)
  • 编译
  • 汇编
  • 链接

  以上这四个阶段就是一个程序在整个编译阶段会经历的四步操作,接下来就让我们详细看一下这四步操作都在干什么。

二、认识编译的四个阶段

(一)预处理

  假设此时我们写了一个名叫mian.c的程序。这是编译的第一阶段,这个阶段会做什么?

  1. 宏替换
  2. 去注释
  3. 引入头文件

 什么是宏替换?

宏替换:将定义的宏直接用值替换掉

 什么是去注释?

去注释:把文件中所写的注释去掉

 什么是引入头文件?

我们在编写代码的过程中,不可避免地要使用库函数,因此会包含对应的头文件,头文件中存储的是库函数的函数声明。这一步就是把头文件中的包含的函数声明等内容复制到我们写的main.c程序中。这里需要注意,头文件中放的都是函数的声明,并不是定义,函数的定义在库中。也就是说,这里是把头文件中的函数声明搬进来了。

  这个阶段执行完成后,生成的文件本质还是一个C程序,因为它只是引入了一些函数声明,去掉了注释,进行了宏的替换。所以这一步并不会发现我们程序的错误,我们把这个新生成的文件称为 main.i 文件。

(二)编译

  编译阶段编译器会对main.i文件做什么?

  1. 语法语义纠错
  2. 把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函数定义在库文件中的位置记录下来,保存到可执行文件中,并不会把函数的具体的实现复制过来。

  当可执行程序运行时,动态库就会被加载到内存中,当可执行文件需要用到哪个函数的话,只需要根据记录在可执行文件中的位置,去内存中的动态库寻找即可。

  1. 好处:当多个程序都使用这个库的时候,只需要加载一个到内存中即可。这样代码冗余更小
  2. 坏处:运行程序时,动态库必须存在,不然去哪里找函数的实现。

三、分步编译

  • 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是指定生成的文件名称。

创建main.c文件
写入main.c文件

(二)预处理

gcc -E main.c -o main.i

生成main.i文件

(三)编译

gcc -S main.i -o main.s

生成mian.s文件

(四)汇编

gcc -c main.s -o main.o

生成main.o文件

(五)链接

gcc mian.o -o mian

生成main文件

(六)运行

运行

四、合并编译

  按照上面的分步编译虽然可以达到我们的预期目标,但是比较麻烦,毕竟敲那么多指令也比较费事,因此推荐采用下面这样的合并编译。

  • 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文件处理到链接阶段完毕。

  上面这些指令可以提高我们的效率,因此通常直接使用第四条指令一步到位。

一步到位main

相关文章:

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(全卷积神经…...

同城外卖跑腿系统源码分析

外卖订餐已经成为很多“社畜”日常不可分割的一部分,足不出户,只需要一部电子设备即可在线订餐,并且可提供的选择非常多样化,与传统的电话订餐外卖模式相比也更便捷的多。 因此,同城外卖跑腿系统源码得以爆火&#xff…...

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&#xff09…...

什么是蜕变测试?

文章目录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安装第三方库时&#xf…...

MIL图像处理那些事:应用程序模块(Mapp)- 初始化和控制MIL应用程序的执行环境

提示:本系列文章通过示例详细介绍MIL图像处理的基础知识及相关操作,让给你快速学会使用MIL进行图像处理 文章目录 前言初始化Mil环境MappAllocMappAllocDefault计时MappTimer异常处理打开和关闭 Mil 异常提示C# try...catch回调函数MappHookFunction查询MappInquire文件操作Ma…...

Pytorch基础语法学习2——argparse模块

一、基本介绍 argparse 模块是 Python 内置的用于命令行参数解析的模块,可以通过少数代码中变量或者参数的改变以实现对整个代码项目的操控。对于大型代码项目(如代码超过1000行),十分便捷 argparse 模块可以让人轻松编写用户友好的命令行接口&#xf…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

ESP32读取DHT11温湿度数据

芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...