『Linux升级路』基础开发工具——gcc/g++篇

news2024/9/20 20:41:43

🔥博客主页:小王又困了

📚系列专栏:Linux

🌟人之为学,不日近则日退 

❤️感谢大家点赞👍收藏⭐评论✍️


目录

一、快速认识gcc/g++

 二、预处理

📒1.1头文件展开 

📒1.2条件编译

二、编译

三、汇编

四、链接

📒4.1库的概念

📒4.2库的特点

📒4.3库的分类

📒4.4动态链接

📒4.5静态链接


🗒️前言:

    在前面的文章中我们学会了vim的用法,可以写一些代码,要想让我们的代码运行起来,还需要我们学会编译工具gcc、g++的使用。C语言既可以使用gcc,也可以使用g++;C++只能使用g++,它们的使用形式是相同的,今天以gcc为主,介绍它们的使用方法,带大家快速上手。

一、快速认识gcc/g++

     当我们写完一段代码,想要编译时可以在命令行输入:gcc code.c,会默认形成a.out的可执行程序。

在输入./a.out,程序就可以执行起来了。

     当我们不想形成默认的可执行,想让它形成指定名称的可执行,可以输入:gcc code.c -o mycode gcc -o mycode code.c

编译主要分为预处理、编译、汇编、链接四个过程,我们将详细讲解这四个过程,带大家学会gcc的使用。

 二、预处理

     此阶段处理以 .c .cpp 为扩展名的源文件,并执行预处理指令。预处理器的主要任务是头文件展开条件编译、展开宏定义、移除注释等。预处理指令都是以#开头的代码行。

  • 指令:gcc -E code.c -o code.i
  • -E:从现在开始进行程序的翻译过程,当预处理做完的时候就停止
  • -o:指目标文件,将当前编译结果写入到code.i文件中 
  •  .i 文件为经过预处理的C语言程序(还是C语言)

📒1.1头文件展开 

     头文件展开,就是在预处理的时候,将头文件拷贝到引用它的源文件中。通过上图我们可以看到,原本14行的代码经过预编译变成了850行。多出的这么多代码,就是把stdio.h文件中的内容插入到当前源文件中。/usr/include/目录是Linux下gcc/g++头文件的默认搜索路径,该路径下有许多和开发相关的头文件。

头文件的展开过程涉及到#include预处理指令。当预处理器遇到#include指令时,它会打开指定的头文件并将其内容插入到当前源文件的位置。这个过程可以分为两种类型的包含:

  • 系统头文件的包含:

使用尖括号<>包含系统头文件,例如:

#include <stdio.h>

预处理器会在系统头文件目录中查找并打开stdio.h文件,并将其内容插入到当前源文件中。

  •  用户头文件的包含:

 使用双引号 “ ” 包含用户定义的头文件,例如:

#include “test.h”

预处理器会在当前源文件所在目录以及指定的包含路径中查找并打开test.h文件,并将其内容插入到当前源文件中。

📒1.2条件编译

     条件编译就是处理条件编译指令,如#if#ifdef#ifndef#else#elif#endif等。根据条件判断是否编译特定代码块。例如:

#ifdef identifier
    // 代码块 A
#else
    // 代码块 B
#endif

如果已经定义了标识符identifier,则编译 // 代码块 A 部分,否则编译 // 代码块 B 部分。

     条件编译最重要的意义就是对头文件的保护,防止头文件被重复包含。

#ifndef HEADER_FILE
#define HEADER_FILE

// 头文件内容

#endif

在展开头文件时,预处理器会继续递归地处理被包含的头文件。这意味着如果一个头文件包含了另一个头文件,那么这个被包含的头文件也会被展开,以此类推,直到所有的头文件都被插入到源文件中。我们使用上面这段条件编译的代码就可以避免这种情况,如果没有定义HEADER_FILE,就执行下面的代码;如果定义了,就不会执行了。

📝条件编译的主要用途包括: 

  • 平台特定代码: 通过条件编译,可以根据不同的操作系统或硬件平台编写特定的代码。

  • 调试和发布版本: 可以使用条件编译来在调试版本和发布版本之间切换代码。

  • 特定功能的开关: 通过条件编译,可以选择性地包含或排除某些功能,以满足特定的编译需求。

  • 配置选项: 根据不同的配置选项选择性地包含或排除代码,以适应不同的编译环境

二、编译

     在这个阶段,预处理后的源代码(通常是.i文件)被翻译成汇编语言。gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。生成的汇编代码描述了程序的控制流、数据等信息。

  • 指令:gcc -S code.i -o code.s
  • -S:从现在开始进行程序的翻译过程,当编译工作做完的时候就停止

三、汇编

     在这个阶段,汇编器将汇编代码(通常是.s文件)翻译成机器码或可重定位的机器码。它将汇编代码转换成二进制目标文件,其中包含特定于处理器体系结构的指令。这个二进制文件也被叫做可重定位目标二进制文件,简称目标文件。但是它不能被执行。

  •  指令:gcc -c code.s -o code.o
  • -c:从现在开始进行程序的翻译过程,当汇编工作做完的时候就停止

📝目标文件为什么不能执行?

     目标文件通常没有定义程序的入口点,即程序的起始地址。可执行文件需要一个明确定义的入口点,从这个点开始执行程序。单独的目标文件可能包含了未解决的符号引用,无法独立执行。可执行文件需要在操作系统上运行,而操作系统提供了运行时支持,包括内存管理、文件操作、进程调度等。没有这些支持,程序很难在操作系统上正确运行。所以,我们还要通过链接来解决这些问题,让目标文件与其他目标文件或库文件进行链接,形成最终的可执行文件。

四、链接

     在这个阶段,链接器将一个或多个目标文件(通常是.o文件)与所需的库文件结合,创建可执行文件。链接的主要任务包括符号解析、地址解析、重定位等,以确保所有部分正确地组合在一起。

  • 指令:gcc  code.o -o mycode

📒4.1库的概念

     库通常指的是包含可重用代码和资源的集合,目的是为了帮助开发者完成特定任务。库可以包含函数、类、变量、子例程等,提供了一组API(应用程序接口)或者工具,使得开发者能够更轻松地完成常见的编程任务,而无需从头开始编写所有的代码。

     我们的C程序中,并没有定义printf的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现printf函数的呢? 答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc会到系统默认的搜索路径/usr/lib下进行查找,会默认找到C的标准库,它会把我们写的源代码经过编译得到的目标文件与库文件进行链接,也就是链接到 libc.so.6 库函数中去,这样就能实现函数printf了,而这也就是链接的作用。

  •  libc.so.6 就是C语言的标准库。 

📒4.2库的特点

  1. 可重用性: 库中的代码可以在不同的程序中被重复使用,从而减少了代码的冗余,提高了开发效率。

  2. 封装性: 库提供了一个封装的接口,隐藏了内部实现的细节,使得开发者可以专注于使用功能而不必关心底层的实现。

  3. 模块化: 库通常被组织成模块,每个模块负责一个特定的功能。这种模块化的设计有助于提高代码的可维护性和可扩展性。

  4. 标准化: 一些库成为了编程的标准,被广泛接受和使用。这样的库通常提供了一些通用的解决方案,被广泛认可并得到社区的支持。

📒4.3库的分类

     库分为两类:动态库静态库。其中Linux环境下,动态库的后缀是.so,静态库的后缀是.a。在Windows环境下,动态库的后缀是.dll,静态库的后缀是.lib。所有的库文件,都遵守相同的命名规则,即:libname.后缀.xxx

  • 静态库(Static Library): 在编译时被链接到程序中,程序在运行前就包含了库的代码。这意味着库的代码被复制到了程序的可执行文件中。

  • 动态库(Dynamic Library): 在运行时被加载到内存中,程序在运行时可以调用库的函数。这样可以减小程序的大小,因为多个程序可以共享同一个库的实例。

 常见的库包括标准库(如C标准库、C++标准库)、图形界面库(如Qt、GTK+)、数学库(如NumPy)、网络库(如libcurl)、以及许多其他领域的专用库。

📒4.4动态链接

     动态链接是一种在程序运行时将代码和数据库链接到程序中的技术。把库中要用到的库函数的地址写到在我们代码中调用这个函数的地方,就是动态链接。

  • 指令ldd 可执行程序,可以查看一个可执行程序所依赖的动态库。

gcc的默认行为是动态链接 

🎀动态链接的优点:

  • 节省内存: 多个程序可以共享同一份库的实例,从而节省内存。
  • 易于更新: 更新库时,不需要重新编译所有依赖于该库的程序。只需替换库的新版本即可。
  • 灵活性: 可以在程序运行时动态加载和卸载库,使得程序更加灵活。

🎀 动态链接的缺点:

  • 依赖性:对库的依赖性强 一旦库丢失,所有使用这个库的程序都无法运行

📒4.5静态链接

     静态链接是一种在程序编译时将所有代码和库链接到一个独立的可执行文件的过程。这意味着在程序运行之前,所有的代码和库已经被合并成一个单独的可执行文件。把库中的代码拷贝到我们的可执行程序中,就是静态链接。

在Linux中默认是没有静态库的,需要我们自己安装。

  • sudo yum install -y glibc-static 
  • gcc code.c -o mycode-static -static
  • 其中 -static表示执行静态链接

🎀静态链接的优点:

  • 独立性: 生成的可执行文件是完全独立的,不需要外部的依赖。这使得程序更容易分发和部署,因为用户只需要一个文件就可以运行程序。
  • 性能: 静态链接的程序在运行时无需进行额外的库加载,因此在一些情况下可能会稍微快于动态链接的程序。

🎀静态链接的缺点:

  • 占用空间: 由于每个可执行文件包含了所需的所有代码和库,因此静态链接的程序通常比动态链接的程序更大。
  • 更新困难: 如果库被更新,需要重新编译并重新分发整个可执行文件,而不仅仅是替换库文件。

本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位读者三连支持。文章有问题可以在评论区留言,博主一定认真认真修改,以后写出更好的文章。你们的支持就是博主最大的动力。

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

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

相关文章

Unity UGUI的HorizontalLayoutGroup(水平布局)组件

Horizontal Layout Group | Unity UI | 1.0.0 1. 什么是HorizontalLayoutGroup组件&#xff1f; HorizontalLayoutGroup是Unity UGUI中的一种布局组件&#xff0c;用于在水平方向上对子物体进行排列和布局。它可以根据一定的规则自动调整子物体的位置和大小&#xff0c;使它…

案例023:基于微信小程序的童装商城的设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

大数据量条件SQL查询内存处理方案以及数据过滤算法优化

MySQL是一个广泛使用的关系型数据库管理系统。通过SQL语言进行数据操作和查询&#xff0c;还支持多用户、多线程和分布式操作等功能。 在实际使用中&#xff0c;我们会遇到各种查询条件&#xff0c;如字段名、表名、逻辑运算符、比较运算符、函数等。其中&#xff0c;有些查询…

模电知识点总结(二)二极管

系列文章目录 文章目录 系列文章目录二极管二极管电路分析方法理想模型恒压降模型折线模型小信号模型高频/开关 二极管应用整流限幅/钳位开关齐纳二极管变容二极管肖特基二极管光电器件光电二极管发光二极管激光二极管太阳能电池 二极管 硅二极管&#xff1a;死区电压&#xf…

ruoyi 若依框架采用第三方登录

在项目中&#xff0c;前后端分离的若依项目&#xff0c;需要通过统一认证&#xff0c;或者是第三方协带认证信息跳转到本系统的指定页面。需要前后端都做相应的改造&#xff0c;由于第一次实现时已过了很久&#xff0c;再次重写时&#xff0c;发现还是搞了很长时间&#xff0c;…

新材料制造ERP用哪个好?企业应当如何挑选适用的

有些新材料存在特殊性&#xff0c;并且在制造过程中对车间、设备、工艺、人员等方面提出更高的要求。还有些新材料加工流程复杂&#xff0c;涉及多种材料的请购、出入库、使用和管理等环节&#xff0c;解决各个业务环节无缝衔接问题是很多制造企业面临的管理难题。 新材料制造…

【实验笔记】C语言实验——降价提醒机器人

降价提醒机器人 题目&#xff1a; 小 T 想买一个玩具很久了&#xff0c;但价格有些高&#xff0c;他打算等便宜些再买。但天天盯着购物网站很麻烦&#xff0c;请你帮小 T 写一个降价提醒机器人&#xff0c;当玩具的当前价格比他设定的价格便宜时发出提醒。 输入格式&#xf…

使用C++从0到1实现人工智能神经网络及实战案例

引言 既然是要用C++来实现,那么我们自然而然的想到设计一个神经网络类来表示神经网络,这里我称之为Net类。由于这个类名太过普遍,很有可能跟其他人写的程序冲突,所以我的所有程序都包含在namespace liu中,由此不难想到我姓刘。在之前的博客反向传播算法资源整理中,我列举…

IIC驱动OLED HAL库+CubeMX

一.IIC传输数据的格式 1.写操作 2.读操作 3.IIC信号 二. IIC底层驱动 #define SCL_PIN GPIO_PIN_6 #define SDA_PIN GPIO_PIN_7#define SCL_PORT GPIOB #define SDA_PORT GPIOB/********************** 函数宏定义 **********************/ #d…

element-ui表格无法横向拖动问题

是不是用到了fixed // 因为我只有在小屏显示不下的时候才会出现这个问题所以我在这里做了适配(建议把样式放在全局) media screen and (max-width: 1800px) {// 由于使用了fixed导致横向条无法拖动出现bug.Table-page .el-table__fixed {height: auto !important;bottom: 2px …

在ASP.NET Core 中使用 .NET Aspire 消息传递组件

前言 云原生应用程序通常需要可扩展的消息传递解决方案&#xff0c;以提供消息队列、主题和订阅等功能。.NET Aspire 组件简化了连接到各种消息传递提供程序&#xff08;例如 Azure 服务总线&#xff09;的过程。在本教程中&#xff0c;小编将为大家介绍如何创建一个 ASP.NET …

[架构之路-249]:目标系统 - 设计方法 - 软件工程 - 需求工程- 需求开发:如何用图形表达需求,结构化方法的需求分析

目录 一、概述 二、数据模型&#xff1a;E-R图/实体关系图&#xff08;数据单元之间的结构关系&#xff09; 三、功能模型&#xff1a;数据流图DFD&#xff08;逻辑运算&#xff0c;包括输入和输出&#xff0c;实体之间的关系&#xff09;&#xff1a;输入》处理 》 输出 四…

Mysql 锁机制分析

整体业务代码精简逻辑如下&#xff1a; Transaction public void service(Integer id) {delete(id);insert(id); }数据库实例监控&#xff1a; 当时通过分析上游问题流量限流解决后&#xff0c;后续找时间又重新分析了下问题发生的根本原因&#xff0c;现将其总结如下&#xf…

使用端口扫描工具解决开放端口威胁并增强安全性

从暴露网络漏洞到成为入侵者的通道&#xff0c;开放端口可能会带来多种风险向量&#xff0c;威胁到网络的机密性、完整性和可用性。因此&#xff0c;最佳做法是关闭打开的端口&#xff0c;为了应对开放端口带来的风险&#xff0c;网络管理员依靠端口扫描工具来识别、检查、分析…

JS中的OOP

JS中的OOP OOP 为我们解决了什么问题&#xff1f;想象一下&#xff0c;我们希望为教师提供一个平台&#xff0c;每位注册的教师都可以提交分数&#xff0c;并为课程分配作业和其他内容。 如果有一个地方&#xff08;在本例中是一个对象&#xff09;&#xff0c;可以访问所有教…

uboot中nfs和tftp方式获取文件

NFS文件系统挂载 服务器端配置如下 1.Server端需要安装NFS服务&#xff1a; sudo apt-get install nfs-kernel-server2.创建需要挂载的路径&#xff1a; mkdir -p /home/workspace/mercury/nfs_path3.创建共享目录&#xff1a; ①vim /etc/exports ②在文件中添加&#xff…

合并两个有序链表,剑指offer,力扣

目录 力扣题目地址&#xff1a; 原题题目&#xff1a; 我们直接看题解吧&#xff1a; 解题方法&#xff1a; 审题目事例提示&#xff1a; 解题思路&#xff1a; 具体流程如下&#xff1a; 代码实现&#xff1a; 知识补充&#xff1a; 力扣题目地址&#xff1a; 21. 合并两个有序…

git查看某个commit属于哪个分支方法(如何查看commit属于哪个分支)

有时候&#xff0c;当我们由于业务需求很多时&#xff0c;基于同一个分支新建的项目分支也会很多。 在某个时间节点&#xff0c;我们需要合并部分功能点时&#xff0c;我们会忘了这个分支是否已经合入哪个功能点&#xff0c;我们就会查看所有的commit记录&#xff0c;当我们找到…

2024-NeuDS-数据库题目集

一.判断题 1.在数据库中产生数据不一致的根本原因是冗余。T 解析&#xff1a;数据冗余是数据库中产生数据不一致的根本原因&#xff0c;因为当同一数据存储在多个位置时&#xff0c;如果其中一个位置的数据被修改&#xff0c;其他位置的数据就不一致了。因此&#xff0c;在数据…

GPIO HAL库+CubeMX

以正点原子精英版为例&#xff1a; 一.创建HAL库模块 二.GPIO输出 1.自己编写 void led_init(void) {GPIO_InitTypeDef gpio_init_struct;__HAL_RCC_GPIOB_CLK_ENABLE();gpio_init_struct.Pin GPIO_PIN_5;gpio_init_struct.Mode GPIO_MODE_OUTPUT_PP;gpio_init_struct.Spee…