Linux编译器-gcc/g++使用

🪐🪐🪐欢迎来到程序员餐厅💫💫💫
          主厨:邪王真眼
主厨的主页:Chef‘s blog  
所属专栏:青果大战linux
总有光环在陨落,总有新星在闪烁

gcc概述

GCC是GNU Compiler Collection的缩写,是一款自由软件、跨平台的编译器。它支持多种语言,包括C、C++、Objective-C、Fortran、Ada等,可运行在多种操作系统上,如Linux、Windows、macOS等。GCC可以将源代码编译成目标代码,并链接成可执行文件。除此之外,GCC还提供了许多优化选项,可以对生成的代码进行优化,使程序的性能得到提升。GCC的源代码也是开源的,任何人都可以自由地查看和修改它

gcc是GCC中的c语言编译器,而g++是GCC中的c++编译器,二者的用法几乎一模一样,所以我们今天只讲gcc

我们学过c语言的都知道,从c语言源代码到最后的可执行程序要经过以下是四个阶段
  1. 预处理(进行宏替换)
  2. 编译(生成汇编)
  3. 汇编(生成机器可识别代码)
  4.  连接(生成可执行文件或库文件)

我们可以通过gcc生成他们所对应的文件,从而了解各个部分的作用。

但是,为什么呢?为什么是这四个步骤呢?这就涉及到编译器自举了。


编译器自举

计算机语言的发展

我们都知道计算机刚出来的时候是没有c、c++、java这些语言的,那时候我们是通过打孔的纸条来对计算机输入数据的,如果有孔就是0,没孔就是1,与二进制相对应。但是这种方式的效率太低了,后来行业里的大佬便发明了汇编语言,基于此,操作系统、编译器这些东西才逐渐出现,再后来人们又对效率感到不满,于是c语言诞生了,最后就是一生二,二生三、三生万物,不计其数的编程语言被发明出来了。

编译器的发展

要知道,计算机只能看懂二进制语言,后来发明的汇编c语言什么的虽然让程序员用着爽了,可是人家计算机根本看不懂啊,于是编译器登场了,它就是连起人和计算机的一座桥梁。对于最早的语言汇编来说,我们用二进制语言写出编译器,它的功能就是把各种汇编代码转化为二进制使计算机看懂,在这之后我们的汇编就可以被计算机看懂了、可以用来编程了,于是我们又用汇编写了汇编的编译器。同理,在C语言出来之后,我们无法用C语言写一个C语言的编译器,所以就用汇编语言写一个C语言的编译器。现在C语言就可以被计算机编译了,于是我们就可以再用C语言写一个C语言的编译器。

这个时候就出现了一个问题,我们的C语言编译器是直接把C语言转化为二进制,还是C语言转化为汇编,汇编再转化为二进制呢?有人或许会说:直接转化二进制多好,一步到位了啊,但是我们要知道二进制是非常反人类的,直接把C语言转化为二进制是一件很困难的事,但汇编相对于二进制就简单很多,而且汇编转二进制的部分前人也已经写好了,于是我们最终选择了第二种方法,这即是为什么C语言有预编译,编译,汇编这三个过程

编译器自举的过程大致分为两步,第一步是用已有的编译器编译出一个最简单的版本,第二步是使用这个最简单的版本来编译出完整的编译器。这样就可以用新生成的编译器替换旧的编译器,从而实现编译器的更新和升级。


gcc的编译过程

我们先创建测试文件a.c,并且写入一些内容,如下所示

预处理

预处理功能主要包括头文件展开、去注释、宏替换、条件编译
gcc –E a.c –o a.i
  1. 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程
  2.  选项“-o”后接生成的文件的文件名
  3. “a.i”文件为已经a.c预处理后生成的文件

注意:在预处理之后,我们的文件发生了很大的变动,但是,他依旧是C语言文件,因为编译器没有进行语言之间的转化

可以看到,右边的预处理扣的文件直接暴增到八百多行,除此之外还有一些别的变化,我们一一分析
  1. 头文件展开:增加的这个八百多行就是原本我们的<stdio.h>里的东西
  2. 删除注释:我们可以看到原本在a.c中被注视掉的哪一行printf函数在a.i文件中不见了,这是因为在预处理阶段编译器会删掉注释(毕竟注释是给程序员看的,又不是给编译器看的)
  3. 宏替换:a.c中的#define N 100  宏不见了,而且后面prin头发里的M变成了100,这就是对宏的替换
我们再来看看条件编译
我们先把a.c重写一下
接着预编译得到文件a.i
我们发现main函数里除了注释还少了很多东西,这就是条件编译的作用
我们先来翻译一下a.c的条件编译
#ifdef N//如果N被宏定义了那就执行下面的代码
  printf("%d\n",N);
 #elif  M  //如果M被宏定义了且N没有被宏定义那就执行下面的代码                                                                                                                                                                                                   
 printf("%d\n",M);
 #else//若果MN都没有宏定义那就只想下面的代码
 printf("No define\n");
  #endif//条件编译结束

在预处理阶段,编译器会根据条件编译的结果对源代码进行删除或保留从而得到新文件

在LInux下,我们可以在命令行中定义宏

gcc a.c -o a.i -D M=1

他的作用等价于在a.c开头写了#define M=1

我们现在来思考一个问题

现在我开发了一款软件,我设置了免费版的和收费版,收费版的会有更多更好的服务,免费的只有一些基本功能,那么问题来了,难道我要维护两份源代码吗?要知道维护的代码越多成本肯定越高

这时候既可以用到条件编译,我们把免费的和收费的有区别的地方用条件编译包起来,这样维护时只需要维护完整的代码,而发行免费版本就用条件编译发型阉割版的,收费的就用条件编译法完全体

因此条件编译的最重要的应用场景就是一份代码发行多个版本的软件。


编译

在这个阶段中 ,gcc 首先要检查代码的规范性、是否有语法错误等 , 以确定代码的实际要做的工作 , 在检查无误后,gcc 把代码翻译成汇编语言。
用户可以使用 “-S” 选项来进行查看 , 该选项只进行编译而不进行汇编 , 生成汇编代码。
实例 : gcc –S a.i –o a.s

我们可以看到现在代码已经变成了汇编语言


汇编

汇编阶段是把编译阶段生成的 “.s” 文件转成目标文件
读者在此可使用选项 “-c” 就可看到汇编代码已转化为 “.o” 的二进制目标代码了
实例 : gcc –c a.s –o a.o
我们打开文件发现是一堆乱码,这是因为我们的vim编辑器是对文本文件进行处理的,用它直接打开二进制文件就会显示乱码

gcc下的链接

在成功编译之后 ,就进入了链接阶段,完成了链接之后 ,gcc 就可以生成可执行文件.
要将我们刚才创建的a.c、a.i、a.o 、a.s变成可执行文件我们只需要使用gcc 文件名就行,如果要指定生成的可执行文件名字就加上 -o 【你改的名字】
实例: gcc a.c –o a.exe

我们要知道在window操作系统会根据文件后缀区分文件。但是linux不会,你可以随意指定后缀,但我们最好还是按window下的规则,因为这样也方便我们自己观看

链接作用

我们在a.c中调用了printf函数,我们知道要使用一个函数分为 函数声明、函数定义、函数调用 三个步骤
我们在main中进行函数调用、在头文件中包含了函数声明,那么函数定义呢?他在哪
最后的答案是 :
系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了 , 在没有特别指定时 ,gcc 会到系统默认的搜索路径“/usr/lib” 下进行查找 ,即可 链接到 libc.so.6 库函数中去 , 这样就能实现函数“printf” , 而这也就是链接的作用。

静态库和动态库

库的后缀

在windows下动态库的后缀是.dll,静态库的后缀是.lib

linux下动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。

库的命名:libname.so.XXX

注意库本质上就是一个文件,有到这个文件的路径,它就是把很多个源文件给你打包编译成一个文件了,达到既可以使用功能又可以隐藏源文件的目的。
事实上我们的linux系统中是下载了很多库的,也正因此我们才可以编写代码
  • 静态库

是指编译链接时 , 把库文件的代码全部加入到可执行文件中 ,
缺点:生成的文件比较大
优点:在运行时也 就不再需要库文件了。
  • 动态库
在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时 链接文件加载库,当程序执行到指定的代码段,就会去动态库内部查找对应的内容。
优点:这样可以节省系统的开销。
缺点:一旦丢失,所有链接该库的程序都无法执行了
  • 查看库
1.我们可以通过下面的指令查看该文件连接了哪些库
ldd 文件名
第二行的结果就表明我们链接了c标准库
2.我们可以使用file指令查看,输入
file a.exe
这里的 dynamical linked就是动态链接,说明我们用的是动态库
  • 使用静态库
如果我们想要生成静态链接的文件,则额外加上选项-static
gcc -o a.exe a.c -static

但是不出意外,你的操作系统会报错

/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status

这是因为你还没有下载静态库到linux中,我们需要手动下载,记得是root权限

yum install -y glibc-static libstdc++-static

 我们分别用静态库和动态库链接同一个文件看看区别

[qingguo@iZf8z6fhz4n89uhtqx9ey6Z ~]$ gcc -o a.exe.static a.c -static 
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z ~]$ gcc -o a.exe a.c

可以发现静态库的链接结果是动态库的100倍!!!可以看出它对空间的消耗是真的大

对它使用ldd,发现确实不是动态库

[qingguo@iZf8z6fhz4n89uhtqx9ey6Z ~]$ ldd a.exe.static
	not a dynamic executable

 再用file看看

[qingguo@iZf8z6fhz4n89uhtqx9ey6Z ~]$ file a.exe.static
a.exe.static: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=498e5403fe6a8ef2f42ab2f6b0d70ef20db36827, not stripped

更是明确的告诉你是静态链接


       今天学习了gcc的预编译、编译、汇编、链接四个功能,还补充了编译器自举和静态库、动态库的知识,记得好好复习总结,下一期我们来学习makefile工具


🥰创作不易,你的支持对我最大的鼓励🥰
🪐~ 点赞收藏+关注 ~

e3ff0dedf2ee4b4c89ba24e961db3cf4.gif

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ | Leetcode C++题解之第101题对称二叉树

题目&#xff1a; 题解&#xff1a; class Solution { public:bool check(TreeNode *u, TreeNode *v) {queue <TreeNode*> q;q.push(u); q.push(v);while (!q.empty()) {u q.front(); q.pop();v q.front(); q.pop();if (!u && !v) continue;if ((!u || !v) ||…

Excel插入多行VBA实现

我们还可以利用 VBA&#xff08;Visual Basic for Applications&#xff09;宏语言&#xff0c;在 Excel 中写一个 VBA 宏来自动插入多行数据。这种方法可以方便我们自定义需要插入的行数和插入位置。下面是编写 VBA 宏的步骤&#xff1a; 1、按下Alt F11快捷键&#xff0c;打…

亚马逊云科技介绍

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、亚马逊云科技云计算1.1 云计算的优势 二、领先的云平台三、亚马逊云科技区域的全球网络…

从零开始实现自己的串口调试助手(1) - ui界面搭建

UI 界面搭建 ui界面整体演示 ui对象拆分 更多的细节就不方便展开了&#xff0c;下面有提示完成ui设计的提示 在创建工程前 记得把编码改为utf-8 ui设计技巧: ctrl 鼠标左键实现拖动实现复制粘贴 groupBox &#xff1a; 带标题的文本框 栅格布局 -- 只有一个控件的时候会铺满…

MyBatis中Where标签:揭秘高效SQL构建的秘密

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 理解Where标签的基础概念 在MyBatis中&#xff0c;<where>标签是用于构建SQL查询语句中的一个非常重要的元素。它允许你在一个动态的SQL语句中添加WHERE子句&#xff0c;而不需要担心SQL语法错误或额外的逗号…

记一次重定向问题(浏览器安全)解决

近期做单点登陆功能&#xff0c;本身应该是一个很简单的功能&#xff0c;却发生了意向不到的问题…让我们看下&#xff1a; 首先第三方给出的地址需要通过JWT框架获取token拼接后跳转&#xff0c;我这边为了方便首选肯定是考虑用response.sendRedirect(url)&#xff0c;但是做好…

网络中断时接口status显示canceled,无法捕捉到状态进行相关操作

遇到的问题&#xff1a;如图所示&#xff0c;loading状态栏无法关闭&#xff0c;因为.then和.catch还有.finally 中都无法捕捉到接口canceled的状态&#xff0c;导致一直在loading状态&#xff0c;无法进行操作关闭弹框这一步。 产生原因&#xff1a;客户端 在服务器响应前关闭…

kafka Kerberos集群环境部署验证

背景 公司需要对kafka环境进行安全验证,目前考虑到的方案有Kerberos和SSL和SASL_SSL,最终考虑到安全和功能的丰富度,我们最终选择了SASL_SSL方案。处于知识积累的角度,记录一下kafka keberos安装部署的步骤。 机器规划 目前测试环境公搭建了三台kafka主机服务,现在将详细…

多家知名媒体到访“光子1号金融算力中心“ 交流AI与算力未来观

5月23日&#xff0c;企商在线 “光子1号金融算力中心媒体参观日”活动成功举办&#xff0c;十多家主流媒体、IT行业媒体及自媒体代表走进光子1号金融算力中心&#xff0c;深入了解企商业务发展、战略规划及“光子1号金融算力中心”等企商打造的新型数字基础设施&#xff0c;共同…

基于STC12C5A60S2系列1T 8051单片机的TM1637键盘数码管模块的数码管显示与单片机连接的按键的按键值的功能

基于STC12C5A60S2系列1T 8051单片机的TM1638键盘数码管模块的数码管显示与单片机连接的按键的按键值应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍TM1637键盘数码…

云计算期末复习(1)

云计算基础 作业&#xff08;问答题&#xff09; &#xff08;1&#xff09;总结云计算的特点。 透明的云端计算服务 “无限”多的计算资源&#xff0c;提供强大的计算能力 按需分配&#xff0c;弹性伸缩&#xff0c;取用方便&#xff0c;成本低廉资源共享&#xff0c;降低企…

坚守互联网底层逻辑,搜狐走向长期主义的next level

2024年以来&#xff0c;随着我国经济回升向好态势进一步巩固增强&#xff0c;网络内容供给不断丰富&#xff0c;新型消费持续活跃&#xff0c;互联网板块整体估值向预期进行修正。因此&#xff0c;中概互联网指数ETF&#xff08;KWEB&#xff09;一转颓势&#xff0c;截至5月21…

Aiseesoft Video Converter Ultimate视频转换大师,免安装中文旗舰版 v10.8.32

软件介绍 视频转换大师是一款集转码、编辑以及压缩功能于一身的专业软件&#xff0c;支持处理超过1,000种视频和音频格式。该工具不仅提供基础的格式转换服务&#xff0c;还拓展至高级功能&#xff0c;包括视频效果调整、数据压缩以及ID3信息编辑等&#xff0c;同时&#xff0…

MySQL简单测试和安装

MySQL 的特点 1、MySQL 性能卓越、服务稳定&#xff0c;很少出现异常宕机。 2、MySQL开放源代码且无版权制约&#xff0c;自主性及使用成本低。 3、MySQL历史悠久(版本众多)&#xff0c;用户使用活跃&#xff0c;遇到问题可以寻求帮助。 4、MySQL体积小(相对大型关系型数据库)…

xxl-job入门

对比原有的任务调度 1. 支持可视化的界面 2. 执行任务分片 3. 支持线上集成 安装 拉取gitee项目并解压 xxl-job: 一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。…

python数据处理与分析入门-Pandas数据可视化例子

相关内容 Matplotlib可视化练习 Pandas 数据可视化总结 柱状图 reviews[points].value_counts().sort_index().plot.bar()散点图 reviews[reviews[price] < 100].sample(100).plot.scatter(xprice, ypoints)蜂窝图 reviews[reviews[price] < 100].plot.hexbin(xprice…

数据仓库ETL

小白的数据仓库学习笔记 2024/5/20 18:25 文章目录 ETLdim打开创建项目&#xff08;选这个&#xff0c;这个是做etl的&#xff09;建立元数据的连接同样的&#xff0c;建立与数据仓库的连接新建ssis包序列容器全量etl增量etl建立sql任务双击打开&#xff0c;设置连接、内容 双击…

nohup java -jar 启动java项目,设置linux服务器自启动

研究两天终于完成了,兄弟们点个赞啊 .sh文件需要改成如下图Notepad改 .sh文件内容路径啥的根据自己目录改 if ps aux | grep -v grep | grep "ruoyi-admin.jar"这里改成你自己的jar包 #!/bin/bash # 设置环境变量 export JAVA_HOME/usr/local/java/jdk-17.0.10 e…

Leecode560:和为 K 的子数组

这道题用暴力解法时间复杂度会很高&#xff0c;但是涉及到和等于多少的情况&#xff0c;一般情况下会考虑以空间换时间来存储前面获得的信息&#xff0c;然后将答案为某值的结果返回。 这里利用了累加然后通过哈希表寻找值的思想。就是先将前面的数全部加起来&#xff0c;统计…

区块链fisco联盟链搭建(二)搭建多群组联盟链

本文章只讲搭建的命令方法 以单机、四机构、三群组、八节点的星形组网拓扑为例 第一步创建并进入工作目录&#xff08;继续以fisco为例&#xff09; mkdir /fisco cd /fisco 获取搭链脚本上一篇文章区块链fisco联盟链搭建 (一)搭建单群组四节点联盟链中有 第二步生成多群组…