Linux基础开发工具之Linux编译器的使用(gcc/g++)

news2024/11/25 13:30:33

目录

前言

1.背景知识介绍

2.预处理阶段

3.编译阶段  

4.汇编阶段

5.链接过程

5.1 函数库

5.1.1 静态库和动态库

5.2 链接过程的具体内容

总结


前言

  大家好呀,许久没给大家更新了,对于我们在Linux环境下编程,之前小编只是给大家介绍了有关编辑器vim的相关操作,但是对于我们编辑后关键是生成对应的可执行程序,那么产生可执行程序就一定需要使用我们相关的编译器,那么今天给大家带来的就是我们Linux环境下编译器的使用。


1.背景知识介绍

  首先我们需要知道的就是我们的文件到可执行程序一共需要进行预编译,编译,汇编,链接,四个过程在这个过程中我们的编译器执行的工作是各不相同的,而我们编译器使用的相关指令也是不同的,那么小编就以这个过程逐一给大家介绍我们Linux下编译器的使用方式,这里我们以gcc为例,g++和我们的gcc使用方式是一致的,但是我们的g++针对的是我们c++语言的编译,但同时也能编译我们的C语言程序,而我们的gcc就只是针对我们的C语言程序。

2.预处理阶段

我们的预处理阶段执行的工作主要有宏定义替换,头文件展开,条件编译,去注释等,而这里小编就不给大家详细介绍了,对于该过程小编会在另一篇文章中给大家进行详细的说明,讲解,这里就仅仅给大家简单演示一下即可,但在演示之前有一行相关的命令需要大家了解一下

预处理指令是以#号开头的代码行。

实例: gcc –E hello.c –o hello.i

选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。

选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序

首先我们需要在Linux环境下创建一个文件,然后就是用我们的文件编译相关的代码,如下:

 这里我们可以看到我们的程序中有着对应的有头文件,宏定义,以及注释等,对于条件编译,小编会在另一篇文章中给大家具体介绍。

那么这里我们输入指令:gcc –E text.c –o text.i,产生我们对应的text.i文件

这里我们用vim打开我们的text.i文件看看该具体内容:

 这里我们可以看到在text.i文件中我们的头文件被展开了,实际上我们的头文件是一个800多行的大文本,这里我仅仅给大家截取了部分,这里我们很轻松的观察到我们的注释被删除了,以及我们的宏被替换了。那么预处理后我们接下来进行的就是我们的编译阶段。

3.编译阶段  

在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言,那么我们如何观察到这个现象呢?这里我们就需要给大家介绍一个gcc相关指令去给大家演示这个过程。

我们可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码(编译工作做完就停下来)。

实例: gcc –S hello.i –o hello.s

这里给大家简单演示一下:

 这里我们产生了text.s文件,那么我们打开开一下该内容:

 这里我们可以看到这里显示了汇编代码。

4.汇编阶段

  我们的汇编阶段就是把我们的将我们的汇编代码转化为我们的二进制目标文件,对于编译和汇编两个过程,这里就是简单的给大家一笔带过一下,具体的过程小编会在后续给大家介绍。那么我们如何查看这个结果呢?废话不多说,直接上例子:

这里我们在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了(汇编工作做完就停下来)

实例: gcc –c hello.s –o hello.o

.o文件就是我们的目标文件,但是该不可以独立执行,虽然该已经是二进制文件了,还得经过链接才可以

那么我们看看具体操作:

这里我们打开看一下:

 这里我们看到出现了一堆乱码,这是由于我们这里是二进制文件导致的。

5.链接过程

链接过程实际上就是将可重定位目标二进制文件和库进行链接形成可执行程序,相比于之前的目标文件,我们的链接过程形成的可执行程序就是最后我们最后形成的可独立执行的文件

那么我们这里如何将我们的二进制文件转化为可执行文件呢?这里我们还需要使用到一个指令:

实例: gcc hello.o –o hello

 这里我们生成我们的可执行程序,那么我们需要如何去运行这个可执行程序呢?这里我们的方式是这样的

./text

那么我们这里的原理是什么呢?实际上,linux要运行某个程序就一定要找到这个程序的二进制文件,所以我们通常使用  ./文件名  去运行文件指的就是在当前路径找到我们的二进制文件,但是对于指令的执行我们的操作系统是会到特定的路径去寻找的。

5.1 函数库

首先我们需要了解一个小概念就是,我们的程序为什么能够在我们的操作系统中运行呢?

实际上:我们需要的开发环境除了vs,gcc,g++,更重要的是语言本身的头文件和库(也就是我们的系统中一定要提前或者后续安装上对应的头文件库文件)

我们在安装vs2019时也需要选择对应的开发包,也就是将对于的库或者头文件进行了下载安装

我们Linux关于C语言的头文件放置于我们的/usr/include/目录下

这就说明我们的库对于我们一个程序的运行是极其重要的,那么我们的库究竟在我们的程序运行中充当一个什么角色呢?

我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?

最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用

实际上对于我们的编译型语言,安装开发包,必定是下载安装对应的头文件+库文件,而方法的实现就是在库当中(库其实就是把源文件,经过一定的翻译然后打包———只给你提供一个源文件即可,不用给你提供太多的源文件,也可以达到隐藏源文件的目的)而我们最后的软件也就是我们头文件提供方法的声明+库提供方法的实现+我们的代码。

5.1.1 静态库和动态库

静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”

动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。 gcc hello.o –o hello

那么我们如何知道我们的可执行文件使用的是静态库还是动态库呢?这里我们可以使用file指令去查看:

 这里我们可以看到我们这里进行的是动态链接方式这也是我们gcc默认的链接方式

同时我们也可以使用ldd指令可以查看一个可执行程序所依赖的动态库,也就是

 对应着不同的操作系统和软件我们的动态库和静态库的文件后缀是不同的,他们分别对应的如下:

Linux:.so(动态库),.a(静态库)

windows: .dll(动态库),.lib(静态库)

还有一点就是在我们的机器上只会默认安装动态库,不会安装静态库,而如下就是我们安装静态库的指令:

C语言:yum install -y glibc-static

C++: yum install -y libstdc++-static

5.2 链接过程的具体内容

既然我们存在着我们的动态库以及我们的静态库,那就说明我们所对应得也就存在着我们的动态链接和静态链接两种方式:

1.动态链接:当一个程序在执行过程中不能独立完成就需要跳转到动态库中执行,动态库可以给多个程序提供,因此也被称为共享库,动态库不能缺失,该影响的不是一个程序还有可能导致多个程序无法执行

2.静态链接:该链接过程中会直接将自己要使用的方法拷贝到可执行程序当中,以后的程序就不用再依赖于静态库了

在linux中,编译器形成可执行程序,默认采用的就是动态链接,使用静态链接的方式是:gcc  文件名 -o指定文件名 -static

 这里我们使用file指令去查看一下该链接方式

很明显这里显示的是静态链接。 

其次我们需要注意一下几点:

1.如果我们没有使用静态库,但是我们一定要进行静态链接,这个行为是不行的

2.如果我们没有动态库,只有静态库,而且我们的gcc能找到,那么我们是可以进行动态链接的,这是因为gcc默认优先动态链接-static的本质也就是改变优先级

3.我们的可执行程序不一定是纯的动态链接或者静态链接,而是混合的

4.在设定时就规定我们的动态链接只能使用动态库,静态链接只能使用静态库

那么说了那么多关于动态库,与静态库的想关内容,那么对比于动静态库其都有什么优势劣势呢?

动态库因为是共享库,所以有效的节约资源(磁盘空间,内存空间,网络空间)【优点】

动态库一旦缺失会导所有程序无法运行【缺点】

静态库不依赖于库,程序可以独立运行【优点】

但是静态库体积大消耗资源【缺点】

总结


这里给大家简单的总结一下,我们以程序运行的四个阶段出发给大家介绍了我们编译器在各个过程中执行的任务,可想而知,我们的编译器在我们的程序运行当中是非常重要的一部分,但是程序的一整个实现,运行以及调试过程,我们所需要使用的不仅仅只是我们的编译器,更多的还需要其他工具相互配合使用,那么对于后续如何,我们下回再见。

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

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

相关文章

Ubuntu安装JDK与IntelliJ IDEA

目录 前言 Ubuntu安装JDK 1、更新软件包列表 2、安装OpenJDK 3、验证安装 Ubuntu安装IntelliJ IDEA 1、下载 IntelliJ IDEA 2、解压缩 IntelliJ IDEA 安装包 3、移动 IntelliJ IDEA 到安装目录 4、启动 IntelliJ IDEA 前言 APT(Advanced Package Too…

react 在build读取env 数据

默认会读取.env 文件 npm install dotenv --save npm install dotenv-cli --save-dev例如读取.env.test "build:test": "dotenv -e .env.test react-app-rewired build",.env.test REACT_APP_CURRENTMODE devREACT_APP_Public_Path "https://baid…

VUE中的生命周期、每个生命周期可以干什么

生命周期 就VUE来说就是一个程序的即将创建到销毁的一个过程,也就是vm对象实例从创建到最终销毁的过程。 VUE生命周期4个阶段8个钩子函数(到某一阶段自动调用的函数) 1.初始阶段(虚拟的DOM生成) beforeCreate() 初始化事件对象和生命周期…

width: calc(~“100% - 267px“);动态css 调样式

.result-filtering {color: #8b8b8b;display: flex;// width: 82.6%;width: calc(~"100% - 267px");}

证书文件无法生成.p12

做好的证书文件在生成.p12文件的过程中遇到了.p12选项置灰且无法选择并导出的情况 解决办法 起初认为生成的空白 CertificateSigningRequest 有问题,反反复复尝试几次制作后均无效; 而后发现问题出在了钥匙串访问的选项问题上 ... 将顶部菜单 tab 由"所有选项"切换至…

ActivityWatch配置跨平台同步(没弄完)

安装完后马上给你来个下马威&#xff1a; 具体内容如下&#xff1a; Traceback (most recent call last): File "aw_qt\__main__.py", line 3, in <module> File "click\core.py", line 1130, in __call__ File "click\core.py", l…

docker制作compose

第一步&#xff0c;先了解Compose是什么&#xff1f; Compose 项目是 Docker 官方的开源项目&#xff0c;负责实现对 Docker 容器集群的快速编排。 Compose有两个重要的概念 1.项目 &#xff1a;由一组关联的应用容器组成的一个完整业务单元&#xff0c;在docker-compose.ym…

最受欢迎的8种编程语言解析_kaic

国内目前最受欢迎的8种编程语言解析 在过去的 17 个月&#xff08;2022 年 1 月至 2023 年 5 月&#xff09;时间里&#xff0c;DevJobsScanner 通过分析超 1400 万个开发人员职位&#xff0c;并从中筛选了有明确编程语言需求的职位&#xff0c;得出了在 2023 年需求量最大的 …

Socket基本原理详解

socket的概念 故事要从一个插头说起。 插头与插座 当我将插头插入插座&#xff0c;那看起来就像是将两者连起来了。 风扇与电力系统建立"连接" 而插座的英文&#xff0c;又叫socket。 巧了&#xff0c;我们程序员搞网络编程时也会用到一个叫socket的东西。 其实两者…

[算法通关村] 1.1 单向链表的创建

各位读者朋友们&#xff0c; 从今天开始&#xff0c;我将通过博文的形式&#xff0c;概述数据结构中应知必会的基本算法&#xff0c; 由于我更加熟悉 Java 语言&#xff0c;所以全程使用 Java 语言进行叙述&#xff0c; 如果您发现了文章中的错误&#xff0c;请您不吝赐教。 什…

HCIP——OSPF综合实验

OSPF实验 一、实验拓扑二、实验要求三、实验思路四、实验步骤1、配置接口IP地址以及环回2、配置缺省路由3、配置MGRE环境4、配置OSPF5、修改网络类型6、重发布7、配置汇总空接口防环8、配置特殊区域&#xff1a;9、配置NAT环境10、加快收敛11、配置接口认证12、测试 一、实验拓…

ModHeader插件

ModHeader浏览器插件下载装载地址&#xff1a;&#xff08;microsoftedge&#xff09;ModHeader - Modify HTTP headers - Microsoft Edge Addonshttps://microsoftedge.microsoft.com/addons/detail/modheader-modify-http-h/opgbiafapkbbnbnjcdomjaghbckfkglc?refidbingshor…

MySQL 主从复制的认识 2023.07.23

一、理解MySQL主从复制原理 1、概念&#xff1a;主从复制是用来建立一个和 主数据库完全一样的数据库环境称为从数据库&#xff1b;主数据库一般是准实时的业务数据库。 2、作用&#xff1a;灾备、数据分布、负载平衡、读写分离、提高并发能力 3、原理图 4、具体步骤 (1) M…

微服务远程调用openFeign简单回顾

目录 一. OpenFeign简介 二. OpenFeign原理 演示使用 provider模块 消费者模块 配置全局feign日志 示例源代码: 一. OpenFeign简介 OpenFeign是SpringCloud服务调用中间件&#xff0c;可以帮助代理服务API接口。并且可以解析SpringMVC的RequestMapping注解下的接口&#x…

生物信息学_玉泉路_课堂笔记_04 第四章 高通量测序技术与 数据分析

&#x1f345; 课程&#xff1a;生物信息学_玉泉路_课堂笔记 中科院_2022秋季课 第一学期 &#x1f345; 个人笔记使用 &#x1f345; 2023/7/19 测序技术 鸟枪法测序 全球测试仪的使用情况 边合成边测序 深颜色是加的接头 adapter 浅颜色的是要测的片段 insert ① 重叠的情…

【iOS】动态链接器dyld

参考&#xff1a;认识 dyld &#xff1a;动态链接器 dyld简介 dyld&#xff08;Dynamic Linker&#xff09;是 macOS 和 iOS 系统中的动态链接器&#xff0c;它是负责在运行时加载和链接动态共享库&#xff08;dylib&#xff09;或可执行文件的组件。在 macOS 系统中&#xf…

Docker 安装 和 GPU 支持

一、Docker安装过程&#xff08;ubuntu18.04环境&#xff09; 清华镜像 docker 安装&#xff1a;docker-ce | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 1、由于apt官方库里的docker版本可能比较旧&#xff0c;所以先卸载可能存在的旧版本&…

Java 设计模式——原型模式

目录 1.概述2.结构3.实现3.1.浅拷贝3.2.深拷贝3.2.1.通过对象序列化实现深拷贝&#xff08;推荐&#xff09;3.2.2.重写 clone() 方法来实现深拷贝 4.优缺点5.使用场景 1.概述 &#xff08;1&#xff09;原型模式 (Prototype Pattern) 是一种创建型设计模式&#xff0c;是通过…

【2023裸辞失业后之初学RocketMQ】

目录 RocketMQ概述MQ概述常见的MQ产品常见的协议 Rocket的安装和启动基本概念系统架构安装RocketMQ和控制台 RocketMQ概述 MQ概述 Message Queue&#xff1a;是提供消息队列服务的中间件&#xff0c;提供消息生产&#xff0c;存储&#xff0c;消费的全过程。 作用&#xff1a…

刘铁猛C#语言教程——表达式详解1

表达式的定义 对以上文档的翻译&#xff1a; 对以上文档的代码解释&#xff1a;表达式是为了实现具体的算法逻辑并得到一个具体的值&#xff0c;而表达式的返回值可以是一个单值&#xff0c;也可以是实例&#xff0c;方法&#xff0c;或者命名空间&#xff1b;例如&#xff1a;…