【Linux】环境基础开发工具的使用之gcc详解(二)

前言:上一篇文章中我们讲解了Linux下的vim和yum的工具的使用,今天我们将在上一次的基础上进一步的讲解开放工具的时候。

💖 博主CSDN主页:卫卫卫的个人主页 💞
👉 专栏分类:Linux的深度刨析 👈
💯代码仓库:卫卫周大胖的学习日记💫
💪关注博主和博主一起学习!一起努力!
在这里插入图片描述


目录标题

  • Linux基础开发工具的使用
    • Linux编译器-gcc/g++使用
    • gcc与g++安装
    • gcc程序产生的过程
    • gcc的用法
      • 逐过程讲解
        • 预处理阶段
        • 编译阶段
        • 汇编阶段
        • 链接阶段
    • 动态库与静态库


Linux基础开发工具的使用

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

GCC概念:GCC(GNU Compiler Collection)是一套开源的编程语言编译器工具,由 GNU 项目开发并发布。它是一种跨平台工具,支持多种编程语言,包括C、C++、Objective-C、Fortran、Ada等。GCC不仅仅是一个编译器,而是一个完整的编译器套件,提供了编译、链接、优化等多个功能。G++ 是 GCC 的 C++ 版本,它是 GCC 中专门用于编译和链接 C++ 代码的工具。除了支持 C++ 语言的编译和链接外,G++ 也能够兼容 C 语言代码的编译。


gcc与g++安装

sudo yum install -y gcc
sudo yum install -y gcc-c++ libstdc++-devel

gcc程序产生的过程

在学习C语言阶段我们可以知道:C语言程序从源代码到可执行程序的产生过程可以分为四个阶段:预处理、编译、汇编和链接。
在这里插入图片描述

  1. 预处理阶段:预处理器会处理源代码中的预处理指令,如宏定义、条件编译等。预处理器根据指令将源代码中的宏替换为具体的代码,删除注释,根据条件编译指令决定哪些代码应该被编译。预处理后的代码通常还会生成一个扩展名为 .i 的文件。

  2. 编译阶段:编译器将预处理后的代码转换为汇编语言代码。编译器将 C 语言的代码翻译为机器指令,生成一个扩展名为 .s 的汇编语言文件。

  3. 汇编阶段:汇编器将汇编语言代码翻译为机器码。它会将汇编语言代码转化为可执行文件中的机器指令,生成一个扩展名为 .o 的目标文件。

  4. 链接阶段:链接器将所有的目标文件(.o 文件)和需要的库文件进行链接,生成最终的可执行程序。链接器会解析目标文件中的符号引用,解析库文件中的函数和变量,并将它们合并到最终的可执行文件中,生成一个扩展名为 .exe(Windows)或没有扩展名的可执行文件。

以上四个阶段是编译过程中的基本步骤,每个阶段都有对应的工具和命令来完成。通常情况下,编译器会自动将这四个步骤组织起来,完成整个编译过程,从源代码到可执行程序的生成。
通常 gcc 命令后面不加选项的话,就会默认执行预处理、编译、汇编、链接所有步骤,若程序没有错误的话,我们就可以得到一个可执行文件,默认为 a.out(如下图)
在这里插入图片描述


gcc的用法

在使用gcc命令进行编译时,可以使用不同的参数来指定只进行编译或者只进行预处理等。

  1. 要只进行预处理,可以使用"-E"参数,如下所示
gcc -E file.c #这将只进行预处理,并将预处理结果输出到标准输出。不会进行编译和链接
  1. 要只进行编译,可以使用"-c"参数,如下所示
gcc -S file.c #对文件进行编译而不进行汇编
  1. 使用GCC编译器只生成汇编代码可以通过以下步骤实现
gcc -c filename.c #对文件只进行汇编
  1. 确保已经进行了编译步骤,生成了目标文件(.o文件)输入以下命令进行链接
gcc -o output_file target.o
#其中,output_file是要生成的可执行文件的名称
#target.o是要链接的目标文件的名称。
  1. gcc直接进行编译程序
gcc filename.c -o output
#这个命令会将名为filename.c的C源文件编译成可执行文件
#并将可执行文件命名为output

逐过程讲解

预处理阶段

在预处理阶段:预处理器会处理源代码中的预处理指令,如宏定义、条件编译等。预处理器根据指令将源代码中的宏替换为具体的代码,删除注释,根据条件编译指令决定哪些代码应该被编译。预处理后的代码通常还会生成一个扩展名为 .i 的文件。
gcc执行命令:gcc -E test.c -o test.i (对名为test.c的文件进行预处理,然后生成叫test.i的文件)

[wei@centos7 ~]$ touch test.c
[wei@centos7 ~]$ vim test.c #编辑文件
[wei@centos7 ~]$ gcc -E test.c -o test.i #对文件进行预处理
[wei@centos7 ~]$ ll #查看生成的文件
total 24
-rw-rw-r-- 1 wei wei   310 Feb  2 10:40 test.c
-rw-rw-r-- 1 wei wei 16967 Feb  2 10:40 test.i

例如,我们现在写了这样的一个【test.c】的文件:

  1 #include<stdio.h>                                                                    
  2 #define MAX 1000                                                                   
  3                                                                                      
  4 int main()                                                                           
  5 {                                                                                                                       
  6   printf("hello gcc\n");                                                                                    
  7   printf("hello gcc\n");                                                           
  8   printf("hello gcc\n");                                                                                    
  9   printf("hello gcc\n");                                                                              
 10   int m = MAX;                                                                       
 11   //  printf("hello world\n");                                                                                                                                             
 12   //  printf("hello world\n");                                                                                                                    
 13   //  printf("hello world\n");                                                  
 14   //  printf("hello world\n");                                                                                    
 15   //  printf("hello world\n");                                                        
 16   //  printf("hello world\n");                                                        
 17    return 0;                                                    
 18   }                                                                                                                                           

经过刚刚的命令,我们来查看一下生成的预处理阶段和源文件,关于预处理的内容这里也就不和大家过多的探讨了,想了解的可以看我之前C语言的专栏里面有讲解
在这里插入图片描述


编译阶段

编译阶段:编译器将预处理后的代码转换为汇编语言代码。编译器将 C 语言的代码翻译为机器指令,生成一个扩展名为.s 的汇编语言文件。
gcc执行命令: gcc -S test.i -o test.s (对文件test.i进行编译并命名为test.s)

[wei@centos7 ~]$ gcc -S test.i -o test.s #对文件进行编译
[wei@centos7 ~]$ ll//查看文件
total 28
-rw-rw-r-- 1 wei wei   310 Feb  2 10:56 test.c
-rw-rw-r-- 1 wei wei 16967 Feb  2 10:56 test.i
-rw-rw-r-- 1 wei wei   566 Feb  2 10:57 test.s
[wei@centos7 ~]$ vim test.s //查看编译文件

在这里插入图片描述


汇编阶段

汇编阶段:汇编器将汇编语言代码翻译为机器码。它会将汇编语言代码转化为可执行文件中的机器指令,生成一个扩展名为 .o 的目标文件。
gcc执行命令gcc -c test.s -o test.o (对文件test.s进行汇编并且对汇编生成的文件命名为test.o)

[wei@centos7 ~]$ gcc -c test.s -o test.o #进行汇编
[wei@centos7 ~]$ ll #查看文件
total 32
-rw-rw-r-- 1 wei wei   310 Feb  2 10:56 test.c
-rw-rw-r-- 1 wei wei 16967 Feb  2 10:56 test.i
-rw-rw-r-- 1 wei wei  1680 Feb  2 11:10 test.o
-rw-rw-r-- 1 wei wei   566 Feb  2 11:09 test.s
[wei@centos7 ~]$ vim test.o //查看汇编文件

在这里插入图片描述

这里强调一下此时生成的是一个二进制文件,无论我们有没有权限执行这个文件,最终都是无法直接执行的


链接阶段

链接阶段:链接器将所有的目标文件(.o 文件)和需要的库文件进行链接,生成最终的可执行程序。链接器会解析目标文件中的符号引用,解析库文件中的函数和变量,并将它们合并到最终的可执行文件中,生成一个扩展名为 .exe(Windows)或没有扩展名的可执行文件。
gcc执行命令gcc test.o -o test (对文件test.s进行链接,并命名一个叫test的可执行文件)

[wei@centos7 ~]$ gcc test.o -o test #对文件进行链接并生成一个叫test的可执行文件
[wei@centos7 ~]$ ll
total 44
-rwxrwxr-x 1 wei wei  8360 Feb  2 11:19 test
-rw-rw-r-- 1 wei wei   310 Feb  2 10:56 test.c
-rw-rw-r-- 1 wei wei 16967 Feb  2 10:56 test.i
-rw-rw-r-- 1 wei wei  1681 Feb  2 11:17 test.o
-rw-rw-r-- 1 wei wei   566 Feb  2 11:11 test.s
[wei@centos7 ~]$ ./test #执行文件
hello gcc
hello gcc
hello gcc
hello gcc

当然了这里,如果我们不使用-o选项来指定文件生成的名字时,生成的默认文件的名字就是a.out,这里我们依然和上面保持一致,自己来命名生成的文件的名称(test)。


动态库与静态库

在Linux系统中,可以使用动态库和静态库来组织和共享代码。

动态库(Dynamic Library)是一种在运行时加载的共享库,它包含编译后的代码和数据,可以被多个程序共享使用。每个程序使用动态库时,都不需要将其完整拷贝到自己的内存空间中,而是通过内存映射的方式共享。动态库的文件扩展名通常为.so(Shared Object)。

静态库(Static Library)是一种在编译时被链接到程序中的库,它包含了编译后的代码和数据,每个程序在编译时会将静态库的副本嵌入到自己的可执行文件中。因此,每个程序运行时都有自己独立的静态库副本。静态库的文件扩展名通常为.a(Archive)。

使用动态库的好处是可以实现代码的共享和模块化管理,使得程序的执行效率更高和占用更少的磁盘空间。同时,如果动态库的代码发生更新或修复,只需要替换动态库文件而无需重新编译程序。

使用静态库的好处是在程序的编译时可以确保静态库的一致性,不受其它因素影响。另外,静态库在编译时会被完整地嵌入到程序中,因此可以避免对外部环境的依赖。

在Linux系统中,可以使用gcc编译器来编译和链接程序,使用以下选项来链接动态库和静态库:

链接动态库:使用-l选项加上库名来链接动态库,例如-lm表示链接数学库。

gcc -o program program.c -lm  #program.c是程序的源代码文件,
#-o选项指定生成的可执行文件名,-lm表示链接数学库

链接静态库:使用-L选项加上库的路径来指定静态库的位置,使用-l选项来指定库名。

gcc -o program program.c -L/path/to/library -lmylibrary 
#L选项指定静态库的路径,-l选项指定静态库的名称

动态库和静态库在使用过程中各有优缺点,下面是它们的主要特点:

动态库的优点:

  1. 节省内存:多个程序可以共享同一个动态库,不需要将动态库的完整副本加载到内存中,节省了内存空间。
  2. 易于更新和维护:如果动态库的代码有更新或修复,只需替换动态库文件,不需要重新编译依赖它的程序。
  3. 动态加载:动态库在程序运行时加载,可以根据需要进行加载和卸载,灵活性更高。
  4. 共享性:动态库可以被多个程序共享使用,提高了代码复用性和模块化管理。

动态库的缺点:

  1. 可执行文件与动态库有依赖关系:在运行程序之前,必须保证系统中存在相应的动态库,否则会出现运行错误。
  2. 运行时开销:动态库的加载和链接会在程序运行时产生一定的开销,对于性能要求较高的程序可以考虑使用静态库。

静态库的优点:

  1. 独立性:静态库在编译时被完整嵌入到可执行文件中,无需对外部环境有依赖,保证了程序的独立性。
  2. 性能提升:由于静态库在编译时被完整的嵌入到可执行文件中,因此在运行时不需要加载和链接,可提高程序的运行效率。
  3. 稳定性:静态库在编译时就已经固定,不会受到外部环境或动态库的影响,保证了程序的稳定性。

静态库的缺点:

  1. 内存占用:每个使用静态库的可执行文件都需嵌入静态库的副本,会占用更多的内存空间。
  2. 更新和维护困难:如果静态库的代码有改动,需要重新编译依赖它的程序,并重新分发更新的程序。

根据具体的需求和场景,可以综合考虑动态库和静态库的优缺点来选择合适的库。在一般情况下,动态库适合用于代码的共享和更新,对内存占用和执行效率有一定要求;静态库适合用于确保库的独立性和稳定性,对内存占用和执行效率有较高要求的情况。
注:Linux默认使用的是动态链接和动态库


如果大家没有安装动态库和静态库的话可以使用下面的代码安装:
动态库:sudo yum install -y glibc-static
静态库:sudo yum install -y libstdc++-static


好啦,今天的内容就到这里啦,下期内容预告gdb、make/makefile、进度条的讲解


结语:今天的内容就到这里吧,谢谢各位的观看,如果有讲的不好的地方也请各位多多指出,作者每一条评论都会读的,谢谢各位。


🌏🗺️ 这里祝各位寒假愉快 💞💞

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

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

相关文章

贰[2],Xamarin生成APK

1&#xff0c;生成改为Release版本 2&#xff0c;选中****.Android项目 3&#xff0c;点击生成&#xff0c;选择存档 4&#xff0c;点击分发 5&#xff0c;选择临时 6&#xff0c;添加签名标识 7&#xff0c;选择对应的签名标识&#xff0c;点击另存为

文献阅读:金鱼端脑细胞类型图谱揭示了空间结构和细胞类型进化的多样性

文献介绍 「文献题目」 A telencephalon cell type atlas for goldfish reveals diversity in the evolution of spatial structure and cell types 「研究团队」 Amit Zeisel&#xff08;以色列理工学院&#xff09;、Ronen Segev&#xff08;本古里安大学&#xff09; 「发表…

认识“协议”

协议 协议的概念结构化数据的传输将结构化的数据组合成一个字符串序列化和反序列化协议定制客户端代码服务线程执行例程 协议的概念 协议&#xff0c;网络协议的简称&#xff0c;网络协议是通信计算机双方必须共同遵从的一组约定&#xff0c;比如怎么建立连接、怎么互相识别等…

H12-811_503

503.如下图所示&#xff0c;下列说法正确是&#xff1f;( ) A.主机A和主机B的广播地址相同 B.主机A可以ping通主机B C.主机A和主机B不能获取对方的MAC地址 D.主机A的ARP缓存中存在如下条目10.0.12.5 MAC-B 答案&#xff1a;C 注释&#xff1a; 两个主机IP地址的网…

Elasticsearch:Geoshape query

Geoshape 查询可以用于过滤使用 geo_shape 或 geo_point 类型索引的文档。 geo_shape 查询使用与 geo_shape 或 geo_point 映射相同的索引来查找具有与查询形状相关的形状的文档&#xff0c;并使用指定的空间关系&#xff1a;相交&#xff08;intersect&#xff09;、包含(con…

【代码随想录20】669.修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树

目录 669.修剪二叉搜索树题目描述参考代码 108.将有序数组转换为二叉搜索树题目介绍参考代码 538.把二叉搜索树转换为累加树题目描述参考代码 669.修剪二叉搜索树 题目描述 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树…

Map和Set讲解

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 集合框架 模型 Set 常见方法和说明 Set总结 Map说明 Map常见方法和说明 Map 中HashMap的 …

SpringMVC入门学习(十)----mvc:annotation-driven标签介绍

目录 1、关于mvc:annotation-driven作用2、mvc:annotation-driven在什么时候必须配置3、关于mvc:annotation-driven配合使用的几种情况 回到顶部 1、关于mvc:annotation-driven作用 [1]、<mvc:annotation-driven /> 会自动向容器中注册如下组件&#xff0c;并且会代替…

2024 美国大学生数学建模竞赛 美赛(D题)五大湖水资源调配问题 国际大学生数学建模竞赛| 建模秘籍文章代码思路大全

铛铛&#xff01;小秘籍来咯&#xff01; 小秘籍希望大家都能轻松建模呀&#xff0c;华数杯也会持续给大家放送思路滴~ 抓紧小秘籍&#xff0c;我们出发吧~ 完整内容可以在文章末尾领取&#xff01; 问题一&#xff1a;建立一个包括五大湖和连接从苏必利尔湖到大西洋的河流的…

2024Node.js零基础教程(小白友好型),nodejs新手到高手,(四)NodeJS入门——http协议

041_网络基础概念_IP的介绍 hello&#xff0c;大家好&#xff0c;我们来一起认识一下IP。 在开始介绍 IP 之前&#xff0c;我们首先来介绍一个场景&#xff0c;方便大家去理解 IP 这个概念。比如这会儿强哥正在成都&#xff0c;然后还有另外一个小伙伴&#xff0c;谁呢&#x…

基于OpenCV灰度图像转GCode的单向扫描实现

基于OpenCV灰度图像转GCode的单向扫描实现 引言单向扫描存在的问题灰度图像单向扫描代码示例结论 基于OpenCV灰度图像转GCode的单向扫描实现 本文将介绍如何使用OpenCV库将灰度图转换为GCode&#xff0c;并通过单向扫描实现对图像的激光雕刻。GCode是一种用于控制数控机床和…

史诗级明星联动 酱香珍品醉龙酿让中国酒文化走向世界

史诗级明星联动 酱香珍品醉龙酿让中国酒文化走向世界 秉承百年酱香工艺&#xff0c;融合全球一流酿造技术&#xff0c;酱香珍品醉龙酿全力推动中国酱香风味走向世界&#xff0c;持续引领全球酱香新变革。卓越口感在征服全球各大商业精英、政府人员、明星达人的同时&#xff0c…

Qt5 基于OpenGL实现六轴机械臂三维仿真

需求 在Qt中通过OPenGL方式加载三维模型STL文件&#xff0c;然后将多个结构的STL文件类型的模型进行组装&#xff0c;形成6轴机械臂三维模型的显示&#xff0c;并且可以对每个关节进行关节角度的控制。 新建一个C类STLFileLoader&#xff0c;用于加载STL文件&#xff0c;并进…

pytorch_car_caring 排坑记录

pytorch_car_caring 排坑记录 任务踩坑回顾简单环境问题代码版本问题症状描述解决方法 cuda问题&#xff08;异步问题&#xff09;症状描述解决方法 任务 因为之前那个MPC代码跑出来的效果不理想&#xff0c;看了一天代码&#xff0c;大概看明白了&#xff0c;但要做改进还要有…

张维迎《博弈与社会》多重均衡与制度和文化(3)法律和社会规范的协调作用

社会博弈通常存在多个纳什均衡。许多情况下&#xff0c;多个纳什均衡之间并不存在优劣之分&#xff1b;即使有优劣之分&#xff0c;也很难通过无成本的交流而选择一个特定的纳什均衡。这就产生了对制度和文化的需求。社会制度和社会规范&#xff08;文化、习惯等&#xff09;的…

RIP——路由信息协议

目录 1 内部网关协议 RIP 1.1 协议 RIP 的工作原理 1.2 RIP“距离”的定义 1.3 RIP 协议的三个特点 1.4 RIP 协议的优缺点 1.5 路由表的建立 路由表主要信息和更新规则 2 距离向量算法 3 RIP2 报文 4 坏消息传播得慢 5 启动RIP 启动RIP: router rip 命令 启用和检…

nrm切换镜像源-yarn不生效问题

在说这问题前&#xff0c;大家肯定知道nvn管理node版本&#xff0c;不懂的朋友直接看此文&#xff1a; nvm - nodejs版本管理工具&#xff1a;https://blog.csdn.net/tianlu930/article/details/135988727 要安装node自带npm其实不好用&#xff0c;一般都用再装yarn&#xff0c…

【Java程序设计】【C00196】基于(JavaWeb+SSM)的旅游管理系统(论文+PPT)

基于&#xff08;JavaWebSSM&#xff09;的旅游管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的旅游平台 本系统分为前台、管理员2个功能模块。 前台&#xff1a;当游客打开系统的网址后&#xff0c;首先看到的…

【VSCode 光标返回上一位置】

默认按键 Windows: Alt ← ;或者 鼠标侧键 Linux: Ctrl Alt - ;貌似数字键盘的减号没效果 Mac: Ctrl - 自定义修改方法&#xff1a; VSCode左下角 “管理 / Manage” “键盘快捷方式 / KeyBoard Shortcuts” 搜索 “前进 / Go Forward 或 后退 / Go Back” 双击需…

优思学院|APQP在汽车行业如何运作?

什么是APQP&#xff1f; APQP&#xff0c;或称前期产品质量规划&#xff0c;是一个保证制造业产品质量和满足客户需求的有组织的过程。 APQP从产品设计的最初阶段开始&#xff0c;强调质量和可靠性&#xff0c;贯穿至生产过程&#xff0c;帮助在产品日益复杂&#xff08;例如…
最新文章