Linux :理解编译的四个阶段

news2025/8/6 3:51:01

目录

  • 一、了解编译
  • 二、认识编译的四个阶段
    • (一)预处理
    • (二)编译
    • (三)汇编
    • (四)链接
      • 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

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

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

相关文章

【项目】Java树形结构集合分页,java对list集合进行分页

Java树形结构集合分页需求难点实现第一步:查出所有树形集合数据 (需进行缓存处理)selectTree 方法步骤:TreeUtil类:第二步:分页 GoodsCategoryController分页getGoodsCategoryTree方法步骤:第三…

MySQL数据库基本操作-DQL

概念 数据库管理系统一个重要功能就是数据查询,数据查询不应只是简单返回数据库中存储的数据,还应该根据需要对数据进行筛选以及确定数据以什么样的格式显示。 MySQL提供了功能强大、灵活的语句来实现这些操作。 MySQL数据库使用select语句来查询数据 语…

ansible组件介绍和简单playbook测试

一、ansible inventory 在大规模的配置管理工作中,管理不同业务的机器,机器的信息都存放在ansible的inventory组件里面。在工作中,配置部署针对的主机必须先存放在Inventory里面,然后ansible才能对它进行操作。默认的Ansible的in…

docker常用命令,基于linux+centos7

启动docker systemctl start docker 重启docker systemctl restart docker docker自启动 systemctl enable docker 查看所有docker,包括正在运行的和关闭的 docker ps -a 查看正在运行的docker docker ps 停止正在运行的docker。通过id或者docker名称 do…

Ceph介绍

分布式存储概述 常用的存储可以分为DAS、NAS和SAN三类 DAS:直接连接存储,是指通过SCSI接口或FC接口直接连接到一台计算机上,常见的就是服务器的硬盘NAS:网络附加存储,是指将存储设备通过标准的网络拓扑结构&#xff…

client打包升级

目录 前言 一、client如何打包升级? 二、使用步骤 1.先进行改版本 2.执行打包升级命令 总结 前言 本文章主要记录一下,日常开发中,常需要进行打包升级的步骤。 一、client如何打包升级? # 升级发布版本 ## 修改版本 * 父p…

链表经典面试题【典中典】

💯💯💯链表经典面试题❗❗❗炒鸡经典,本篇带有图文解析,建议动手刷几遍。🟥1.反转链表🟧2.合并两个有序链表🟨3.链表分割🟩4.链表的回文结构🟦5.相交链表&…

74. ‘pip‘不是内部或外部命令,也不是可运行的程序-解决办法

74. pip’不是内部或外部命令,也不是可运行的程序-解决办法 文章目录74. pip不是内部或外部命令,也不是可运行的程序-解决办法1. 课题导入2. 手动配置环境变量1. 准备工作2. 配置步骤3. 命令行安装1. 课题导入 有的同学在使用pip安装第三方库时&#xf…

elasticsearch 分布式搜索引擎1

1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 例如: 在GitHub搜索代码 在电商网站搜索商品 在百度搜索答案 在…

WorksPace一款简化修改IP繁琐重复性工作的高效工具

WorksPace简介 workspace软件中文版是一个集成修改网卡IP、网络扫描、记事本、快速启动的效率工具,前端使用Flutter,后端主要是Dart,少量的后台功能用以前Golang,数据存储使用SQLite。主要是为了简化我在日常工作中的频繁重复操作…

app里未读消息已读、未读是怎么设计的?

也不知道大家目前都用的java编程软件有哪些,毕竟在应用程序中,未读和已读消息的设计取决于应用程序的需求和目标。下面是一些常见的设计模式:一、简单的未读/已读标记简单的未读/已读标记:这是最常见的设计,用户打开应…

Linux - Linux系统优化思路

文章目录影响Linux性能的因素CPU内存磁盘I/O性能网络宽带操作系统相关资源系统安装优化内核参数优化文件系统优化应用程序软件资源系统性能分析工具vmstat命令iostat命令sar命令系统性能分析标准小结影响Linux性能的因素 CPU CPU是操作系统稳定运行的根本,CPU的速…

一元导数与多元求导数总结

前序:文章结构 1.一元导数 ①一般函数求导 因为太简单的原因,事实上一般函数求导不会单独出现,大多数都是出现在各种特殊的求导过程中。只要掌握16个基本求导公式没问题。 ②复合函数求导(主要链式法则) 这种一般是…

流量监管与整形

流量监管与整形概览流量监管介绍流量监管令牌桶流量监管的具体实现单桶单速流量监管双桶单速流量监管双桶双速流量监管流量整形介绍GTS(Generic Traffic Shaping)LR(Line Rate)流量整形与流量监管的区别概览 流量整形是对报文的速…

某美颜app sig参数分析

之前转载过该app的文章,今天翻版重新整理下,版本号:576O5Zu56eA56eAYXBwIHY5MDgw (base64 解码)。 上来先抓个包: jadx搜索关键词 "sigTime",然后定位到这里 看这行代码 cVar.addForm(INoCaptchaComponent.sig, genera…

NAST概述

一、NATS介绍 NATS是由CloudFoundry的架构师Derek开发的一个开源的、轻量级、高性能的,支持发布、订阅机制的分布式消息队列系统。它的核心基于EventMachine开发,代码量不多,可以下载下来慢慢研究。 不同于Java社区的kafka,nats…

C++小白入门

1.1编写程序四步走&#xff1a;创建项目创建文件编写代码运行程序解决方案资源管理器&#xff1a;在新创建的项目下右键“源文件”-添加-“新建项”-“C文件&#xff08;.cpp&#xff09;”&#xff0c;给文件取名#include <iostream> using namespace std;int main() {c…

JavaScript新手学习手册-基础代码(二)

与上篇博客相接 一&#xff1a;函数&#xff1a; 案例&#xff1a;通过函数实现绝对值的输出 方法一&#xff1a; function absoluate(x){if(x>0){return x;}else{ return -x;}} 在控制台调用函数 方法二&#xff1a; var demo1 function(x){if(x>0){return x;}els…

springboot项目如何配置启动端口

文章目录0 写在前面1 配置文件(.yaml)--推荐2 配置文件(.properties)3 IDEA配置--不推荐4 写在最后0 写在前面 项目启动需要一个独立的端口&#xff0c;所以在此记录一下。 根据配置文件的后缀书写格式略有不同。 1 配置文件(.yaml)–推荐 若是.yaml后缀的配置文件&#xff0…

SIP网络定压功放 SIP735T机架式广播终端

一、描述SIP735T是广州新悦网络设备有限公司的一款合并式定压功放&#xff0c;支持标准SIP协议&#xff0c;具有10/100M以太网接口&#xff0c;后面板上有2组AUX音源输入和6.35mm接口的麦克风输入&#xff0c;可以输入本地音源&#xff0c;播放来自网络与本地的音频。同时配置5…