Linux编译器:gcc/g++的使用

我们在学习编译器时,我们不仅要只会使用编译器,还要理解程序的编译过程。一个程序存在两个不同的环境。第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令;第2种是执行环境,它用于实际执行代码。本篇文章将在讲解程序的翻译过程中来介绍gcc/g++的使用。

目录

1.语言的发展以及自举的过程

2. gcc如果完成各个翻译过程

2.1 预处理(进行宏替换)

2.2 编译(生成汇编)

2.3 汇编(生成机器可识别代码)

2.4 链接(生成可执行文件或库文件)

2.4.1 函数库一般分为静态库和动态库两种

2.4.2 动态链接与静态链接


程序的翻译过程:

  1. 预处理(进行宏替换)
  2. 编译(生成汇编)
  3. 汇编(生成机器可识别代码)
  4. 链接(生成可执行文件或库文件)

1.语言的发展以及自举的过程

为什么程序翻译要有怎么多过程,这里通过了解语言的发展以及自举或许可以理解。那么什么是自举呢,就是通过自己的语言实现自己的编译器。那么这时候就有问题:是先有语言还是编译器?我们这里慢慢解释。

最开始,计算机只能识别二进制,我们要向计算机传递信息时,只能通过穿孔纸带让CPU识别,也就是最初的第一代语言:机器语言。

但是于这种语言人类很难理解,为了更好的与计算机进行沟通,发展出了第二代语言:汇编语言,用助记符代替了操作码,用地址符号或标号代替地址码,这样就用符号代替了机器语言的二进制码。使用符号代替二进制码进行相关操作。

这里就可以使用汇编代码写软件了,但是既然可以使用汇编语言写软件,也就可以使用汇编语言写汇编语言的编译器,这里就实现了汇编语言的自举。很明显这里可得:是先规划的语言,再通过语言写的编译器。

后来人们认为汇编语言还是复杂,于是就发展有了第三代语言:高级语言C语言,是一种接近于人们使用习惯的程序设计语言。同汇编语言相同,所以高级语言也可以实现自举,但是这里就有一个问题了:高级语言是先将代码转换为汇编代码,再转换为二进制让机器识别,还是直接转换为二进制让机器识别?

首先我们要知道语言发展的每一步都是经历过很多困难的,二进制重写高级语言与汇编语言重写高级语言相比无疑是比较困难的,所以说用汇编代码写高级语言是更加合适的。

这里就可以理解为什么程序翻译过程中要有编译(生成汇编)和汇编(生成机器可识别代码)的过程了。理解这里之后我们继续讲解。

2. gcc如果完成各个翻译过程

格式 gcc [选项] 要编译的文件 [选项] [目标文件]

2.1 预处理(进行宏替换)

  • 预处理功能主要包括替换宏定义,文件包含(拷贝),条件编译,去注释等。
  • 预处理指令是以#号开头的代码行。
  • 实例: gcc –E hello.c –o hello.i
  • 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
  • 选项“-o”是指定目标文件,“.i”文件为已经过预处理的C原始程序

通过vim编译code1.c文件,然后用 gcc 编译code1.c,如果这里没有加选项 -E,会将程序的翻译过程全部进行完,-E 就是让 gcc 预处理完就停下来,如果不加 -o 会将文件预处理完的内容直接打印到屏幕上。

这里可以用vs指令查看多个文件:

可以发现这里预处理后的 .i 文件比 .c 源文件多出了八百多行,多出的主要是包含头文件,也就是把 stdio.h 的内容拷贝了过来。还通过条件编译,实现了对代码的动态裁剪。宏常量M也被替换,注释也被去除。

这里条件编译就可以理解很多软件有免费版本和收费版本,但只需要维护一份代码。

2.2 编译(生成汇编)

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

 这里也可以直接通过gcc -S .c 文件,-S让文件翻译到编译结束后就停下来。

可以发现 .s 文件内部已经生成了汇编代码。 

2.3 汇编(生成机器可识别代码)

  • 汇编阶段是把编译阶段生成的“.s”文件转成目标文件
  • 读者在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了
  • 实例: gcc –c code.s –o code.o

-c 就是将文件翻译进行到汇编结束后就停下来,这里生成 .o 目标文件

通过vim打开文件,可以发现已经生成了我们看不懂的可重定位二进制文件。 

 可以使用od命令查看二进制文件,但也是看不懂的

gcc 指令记忆 -ESc ,与键盘上的退出键相同,但要注意大小写。

生成文件的后缀 -iso 

2.4 链接(生成可执行文件或库文件)

  • 多个可重定位文件(二进制文件)合并成一个可执行文件,进行符号解析和重定位
  • 实例: gcc code.o –o code,这里gcc不加指令即可直接生成可执行程序。

在当先文件目录下是,直接 ./文件名 即可执行。因为执行一个程序需要找到它的位置,这里是相对路径,. 代表当前目录。

可执行文件是由我们的代码+头文件+库组成的,这里就涉及到的知识,我们下面讲解:

  1. 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?
  2. 最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。lib表示是库文件,.so表示动态库,.6是版本号,所以这个库的名字是c,即c标准库。

2.4.1 函数库一般分为静态库和动态库两种

  1. 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”
  2. 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销,所谓的动态链接,就是把要链接库中的函数地址拷贝到我们可执行程序的特定位置。动态库一般后缀名为“.so”如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。 gcc code.o –o code
  3. gcc默认生成的二进制程序,是动态链接的。
  4. Windows下静态库后缀.lib,动态库后缀.dll

2.4.2 动态链接与静态链接

动态链接优缺点:

  • 优点:形成的可执行程序体积比较小,比较节省资源的
  • 缺点∶稍慢一些,强依赖动态库,动态库没了,所有的依赖这个库的程序都无法运行了

静态链接优缺点︰

  • 优点:无视库,可以独立运行
  • 缺点:体积太大,浪费资源

ldd指令查看可执行程序所依赖的库。gcc 后加-static 可以链接静态库

下面可以发现静态链接比动态链接生成的可执行程序体积要大很多。 

默认情况下,云服务器是没有安装c静态库的,只有动态库,安装方法:

  • C语言静态库:sudo yum install glibc-static
  • C++的静态库: sudo yum install -y libstdc++-static

g++ 可以编译C语言和C++,但是gcc只能编译C语言,其他操作是类似的。

本篇结束!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TrOCR模型微调【基于transformer的光学字符识别】

TrOCR(基于 Transformer 的光学字符识别)模型是性能最佳的 OCR 模型之一。 在我们之前的文章中,我们分析了它们在单行打印和手写文本上的表现。 然而,与任何其他深度学习模型一样,它们也有其局限性。 TrOCR 在处理开箱…

改进YOLOv8:结合ICCV2023|动态蛇形卷积,构建不规则目标识别网络

🔥🔥🔥 提升多尺度、不规则目标检测,创新提升 🔥🔥🔥 🔥🔥🔥 捕捉图像特征和处理复杂图像特征 🔥🔥🔥 👉👉👉: 本专栏包含大量的新设计的创新想法,包含详细的代码和说明,具备有效的创新组合,可以有效应用到改进创新当中 👉👉👉: �…

人工智能-深度学习之残差网络(ResNet)

随着我们设计越来越深的网络,深刻理解“新添加的层如何提升神经网络的性能”变得至关重要。更重要的是设计网络的能力,在这种网络中,添加层会使网络更具表现力, 为了取得质的突破,我们需要一些数学基础知识。 ResNet沿…

碾压Fast Request!IDEA插件推荐:Apipost-Helper

IDEA是一款功能强大的集成开发环境(IDE),它可以帮助开发人员更加高效地编写、调试和部署软件应用程序。我们在编写完接口代码后需要进行接口调试等操作,一般需要打开额外的调试工具,而今天给大家介绍一款IDEA插件&…

远程登录Linux方法(Linux平台相互远程;Windows远程登录Linux、远程编码、文件传输;无法远程登录的问题解决;c程序的编译)

在实际使用Linux系统过程中我们不可避免的需要远程登录Linux,这是因为未来大家使用Linux服务器的时候你所对应的那台Linux服务器不一定提供界面(服务器可能在外地)。本篇将会介绍远程登录Linux的方法。 文章目录 1. SSH介绍2. Linux平台相互远程及文件传输2.1 Linux…

k8s笔记资源限制,亲和和性 污点和容忍

镜像下载失败 当宿主机资源不足时,会把pod kill ,在其他node 重建 在宿主机放可能多的资源 requests(请求) limits(限制) 超出百分比 容器 pod namespace级别 pod使用资源过多,导致宿主机资源不足,会导致重建pod cpu 内存限…

【Proteus仿真】【Arduino单片机】DS18B20温度计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器,使用PCF8574、LCD1602液晶、DS18B20温度传感器等。 主要功能: 系统运行后,LCD1602显示传感器采集温度。 二、软件设计 /*…

WorkPlus AI助理知识问答机器人,助力企业级私有化AI构建

ChatGPT以及其他大语言模型展现了令人惊叹的广博知识、语义理解能力与创造能力。它们能够在会话中承认自身错误并进行改正,还能进行一定程度的逻辑推理,具备多语种翻译与多语言编程等"超能力",可胜任多种自然语言处理任务。 然而&…

【C语言数据结构————————二叉树】

文章目录 文章目录 一、什么是树 树的定义 树的种类 树的深度 树的基本术语 二、满二叉树 定义 满二叉树的特点 三、完全二叉树 定义 特点 四、二叉树的性质 五、二叉树的存储结构 顺序存储结构 链式存储结构 六、二叉树的基本操作 七、二叉树的创建 八、二叉树…

2016Outlook显示正在启动无法进入Outlook

2016Outlook显示正在启动无法进入Outlook 故障现象: 因上次非正常关闭,导致Outlook启动时,一直处于启动界面,无法进入主界面正常工作 故障截图: 故障原因: 数据文件异常导致 解决方案: 1、关…

【FPGA】正确处理设计优先级--或许能帮你节省50%的资源

概述 假如现在有一种方法–可以在不怎么需要修改已有设计的情况下,就可以帮您节省50%的设计资源,那你会试试看吗? 当前市场环境下,更低廉的成本却可获得同等性能无疑是极具诱惑的。本文将介绍一种FPGA设计技术,该技术…

数据结构—二叉树的模拟实现(c语言)

目录 一.前言 二.模拟实现链式结构的二叉树 2.1二叉树的底层结构 2.2通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树 2.3二叉树的销毁 2.4二叉树查找值为x的节点 2.5二叉树节点个数 2.6二叉树叶子节点个数 2.7二叉树第k层节点个数 三.二叉树的遍历 3.1…