【Linux系统编程】——深入理解 GCC/G++ 编译过程及常用选项详解
文章目录
- 1. GCC/G++ 编译过程
- 预处理(Preprocessing)
- 编译(Compilation)
- 汇编(Assembly)
- 连接(Linking)
- 静态链接与动态链接
- 静态链接
- 动态链接
- 静态库和动态库
- GCC 常用选项
- 关于编译器的周边
- 条件编译的应用场景
- 为什么非得把语言变成汇编
- 编译器自举(Compiler Bootstrap)
前言: 在C/C++开发中,编译器扮演着至关重要的角色,帮助我们将源代码转化为计算机可以直接运行的可执行程序。本文将带你深入了解 GCC/G++ 的编译过程、常用编译选项及相关知识,助你提升开发效率和问题定位能力。
⼀般我们的云服务器,C/C++的静态库并没有安装,可以采⽤如下⽅法安装
Centos
yum install glibc-static libstdc++ -static -y
1. GCC/G++ 编译过程
GCC/G++ 的完整编译过程可以分为以下 4 个阶段:
预处理(Preprocessing)
预处理是编译的第一个阶段,主要功能包括:
- 宏替换: 替换代码中定义的宏。
- 条件编译: 根据宏定义有选择地编译部分代码。
- 头文件展开: 将包含的头文件内容插入到代码中。
- 注释去除: 删除代码中的注释。
gcc -E hello.c -o hello.i
- -E:只执行预处理,不进入编译阶段。
- -o:指定输出文件名,.i 文件为经过预处理的代码文件。
编译(Compilation)
编译阶段会:
检查代码的合法性(如语法错误)。
将代码翻译成汇编语言。
gcc -S hello.i -o hello.s
- -S:只进行编译,不执行汇编操作,生成 .s 汇编文件。
汇编(Assembly)
汇编阶段将 .s 汇编文件转化为二进制目标代码,生成 .o 文件(目标文件)。
gcc -c hello.s -o hello.o
- -c:只进行汇编,不执行链接,生成 .o 目标文件。
连接(Linking)
连接阶段将多个 .o 目标文件和库文件链接成一个可执行文件。
gcc hello.o -o hello
- 默认链接动态库(如 libc.so.6),生成的可执行文件可以直接运行。
静态链接与动态链接
在实际开发中,通常需要多个源文件协作完成一个程序,而这些源文件之间往往存在函数调用的依赖关系。为了解决这种依赖问题,编译器提供了 静态链接 和 动态链接 两种方式。
静态链接
定义: 在编译链接阶段,将库文件的代码直接嵌入到可执行文件中。
在我们的实际开发中,不可能将所有代码放在⼀个源⽂件中,所以会出现多个源⽂件,⽽且多个源⽂件之间不是独⽴的,⽽会存在多种依赖关系,如⼀个源⽂件可能要调⽤另⼀个源⽂件中定义的函数,但是每个源⽂件都是独⽴编译的,即每个*.c⽂件会形成⼀个*.o⽂件,为了满⾜前⾯说的依赖关系,则需要将这些源⽂件产⽣的⽬标⽂件进⾏链接,从⽽形成⼀个可以执⾏的程序。这个链接的过程就是静态链接。静态链接的缺点很明显:
浪费空间:因为每个可执⾏程序中对所有需要的⽬标⽂件都要有⼀份副本,所以如果多个程序对同⼀个⽬标⽂件都有依赖,如多个程序中都调⽤了printf()函数,则这多个程序中都含有printf.o,所以同⼀个⽬标⽂件都在内存存在多个副本;
更新⽐较困难:因为每当库函数的代码修改了,这个时候就需要重新进⾏编译链接形成可执⾏程序。但是静态链接的优点就是,在可执⾏程序中已经具备了所有执⾏程序所需要的任何东西,在执⾏的时候运⾏速度快。
优点:
- 运行时无需依赖外部库,执行速度快。
缺点:
- 文件体积较大,多个程序共享库文件时会浪费存储空间。
更新库代码后,需要重新编译所有相关程序。
静态库文件后缀: .a(Linux)或 .lib(Windows)。
动态链接
定义: 在运行时将库文件链接到程序中,节省存储空间和系统资源。
优点:
- 程序体积小,节省内存。
更新库文件后,无需重新编译相关程序。
缺点:
- 运行时需要依赖动态库,若缺失动态库则程序无法运行。
动态库文件后缀: .so(Linux)或 .dll(Windows)。
查看动态链接的库:
ldd hello
输出:
linux-vdso.so.1 => (0x00007fffeb1ab000)
libc.so.6 => /lib64/libc.so.6 (0x00007ff776af5000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff776ec3000)
静态与动态链接示例
生成静态链接文件:
gcc -static hello.o -o hello
可执行文件中包含所有依赖的库代码,运行时无需依赖外部动态库。
生成动态链接文件:
gcc hello.o -o hello
默认情况下,GCC 使用动态链接,文件体积较小,运行时依赖动态库。
在这⾥涉及到⼀个重要的概念: 库
• 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,⽽没有定义函数的实现,那么,是在哪⾥实“printf”函数的呢?
• 最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库⽂件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进⾏查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,⽽这也就是链接的作⽤
静态库和动态库
静态库是指编译链接时,把库⽂件的代码全部加⼊到可执⾏⽂件中,因此⽣成的⽂件⽐较⼤,但在运⾏时也就不再需要库⽂件了。其后缀名⼀般为“.a”
• 动态库与之相反,在编译链接时并没有把库⽂件的代码加⼊到可执⾏⽂件中,⽽是在程序执⾏时由运⾏时链接⽂件加载库,这样可以节省系统的开销。动态库⼀般后缀名为“.so”,如前⾯所述的libc.so.6 就是动态库。gcc 在编译时默认使⽤动态库。完成了链接之后,gcc 就可以⽣成可执⾏⽂件,如下所⽰。 gcc hello.o –o hello
• gcc默认⽣成的⼆进制程序,是动态链接的,这点可以通过 file 命令验证。
- Linux下,动态库XXX.so, 静态库XXX.a
- Windows下,动态库XXX.dll, 静态库XXX.lib
GCC 常用选项
GCC 提供了丰富的编译选项,帮助开发者灵活地控制编译过程。以下是一些常用选项的介绍:
- 基本编译选项
-E:仅执行预处理。
-S:执行编译,生成汇编代码,不进行汇编。
-c:执行汇编,生成目标代码,不进行链接。
-o :指定输出文件名称。 - 链接相关选项
-static:生成静态链接的可执行文件。
-shared:生成动态库文件(.so)。
默认情况下,GCC 使用动态链接。 - 优化相关选项
-O0:不进行优化(默认)。
-O1:进行基本优化。
-O2:进行更高级别的优化,权衡运行效率和编译时间。
-O3:最高优化级别,开启所有优化选项。 - 调试相关选项
-g:生成调试信息,供调试器(如 gdb)使用。
-w:不生成任何警告信息。
-Wall:生成所有警告信息,建议开发时开启。
关于编译器的周边
条件编译的应用场景
什么是条件编译?
条件编译是通过宏定义或者预处理指令,控制代码的某些部分在编译时是否被包括进编译过程的功能。它通过预处理指令(如 #ifdef、#ifndef、#if)实现。
应用场景:
多平台兼容
条件编译可以根据操作系统或者硬件平台生成不同的代码。
#ifdef _WIN32
printf("Running on Windows\n");
#else
printf("Running on Linux\n");
#endif
这段代码会根据操作系统定义,选择性地编译不同的部分,从而实现跨平台兼容。
调试与发布
在开发和调试阶段,通常需要输出大量的日志信息,但在发布版本中不希望这些日志被编译进去。条件编译可以帮助实现这一需求。
#define DEBUG
#ifdef DEBUG
printf("Debugging...\n");
#endif
如果 DEBUG 宏被定义,则会输出调试信息;否则,这段代码不会被编译。
还有节约资源、功能模块化、版本控制等场景!
为什么非得把语言变成汇编
编译器的职责
编译器的职责是将高级语言(如 C/C++)编写的程序,转换为计算机可以理解并执行的低级语言(机器代码)。在这个过程中,汇编语言作为一个中间步骤,是不可或缺的。
原因详解
硬件直接执行机器代码
计算机硬件只能理解机器码(由 0 和 1 组成的二进制指令)。因此,无论程序用哪种高级语言编写,最终都必须被转换为机器码。
汇编语言是机器码的可读形式
汇编语言是一种人类可读的机器码表示形式,它将二进制指令映射为助记符(如 MOV、ADD)。将高级语言转化为汇编语言,可以更容易地检查、优化和调试程序。
编译器优化的便利性
编译器将高级语言代码转化为汇编语言,可以应用一系列优化技术(如寄存器分配、指令重排序等),以生成高效的机器码。
多平台适配性
汇编语言是与具体硬件架构相关的。如果编译器直接生成机器码,可能难以适配不同的平台。生成汇编语言后,可以通过调用汇编器生成适合目标平台的机器码。
调试和错误检查
转换为汇编语言后,开发者可以通过反汇编工具查看生成的汇编代码,从而更容易找到性能瓶颈或逻辑错误。
历史原因
早期的计算机直接通过汇编语言编程,高级语言的编译器是后来发展的。为了保持兼容性和硬件操作的透明性,汇编语言仍然是现代编译器中一个重要的中间步骤。
总结 将语言转化为汇编的步骤是编译器中一个关键的阶段,它在硬件和高级语言之间建立了一座桥梁,使程序既能保持可读性,又能高效运行。
编译器自举(Compiler Bootstrap)
什么是编译器自举?
编译器自举是指使用一个已有的简单版本编译器,来开发并编译更加复杂或功能完整的编译器。这种过程通常用于构建编译器自身。
为什么需要自举?
解决编译器的“鸡与蛋”问题
编译器需要用某种语言实现。如果用目标语言本身实现编译器,如何运行该编译器?自举解决了这一问题。
验证编译器的正确性
如果一个编译器能够成功地编译自身并运行生成的版本,说明这个编译器的实现是可靠的。
便于跨平台移植
一个简单的自举编译器可以快速移植到新平台上,然后用它生成完整版本的编译器。
以 C 编译器为例:
第一阶段:
用汇编语言实现一个简单的 C 编译器(只支持部分语法)。
第二阶段:
用第一阶段的编译器编写一个功能更完善的 C 编译器。
第三阶段:
用第二阶段的编译器编译自身,生成最终的完整编译器。
相关文章:
【Linux系统编程】——深入理解 GCC/G++ 编译过程及常用选项详解
文章目录 1. GCC/G 编译过程预处理(Preprocessing)编译(Compilation)汇编(Assembly)连接(Linking) 静态链接与动态链接静态链接动态链接静态库和动态库 GCC 常用选项关于编译器的周边…...
Mac安装配置使用nginx的一系列问题
brew安装nginx https://juejin.cn/post/6986190222241464350 使用brew安装nginx,如下命令所示: brew install nginx 如下图所示: 2.查看nginx的配置信息,如下命令: brew info nginxFrom:xxx 这样的,是n…...
Vue3中使用组合式API通过路由传值详解
在Vue 3中,使用组合式API来传递路由参数是一种常见的需求。Vue Router 是 Vue.js 的官方路由管理工具,可以在不同的场景下通过多种方式传递和接收路由参数。下面将详细讲解几种常见的路由传值方式,并提供相应的代码示例。 1. 通过路由参数传…...
两分钟解决 :![rejected] master -> master (fetch first) , 无法正常push到远端库
目录 分析问题的原因解决 分析问题的原因 在git push的时候莫名遇到这种情况 若你在git上修改了如README.md的文件。由于本地是没有README.md文件的,所以导致 远端仓库git和本地不同步。 将远端、本地进行合并就可以很好的解决这个问题 注意:直接git pu…...
浏览器安全(同源策略及浏览器沙箱)
一、同源策略(Same Origin Policy) 1.定义 同源策略(Same - origin Policy)是一种浏览器的安全机制。它规定一个网页的脚本只能访问和操作与它同源的资源。这里的 “源” 包括协议(如 http、https)、域名&…...
w~Transformer~合集11
我自己的原文哦~ https://blog.51cto.com/whaosoft/12472192 #LightSeq 最高加速9倍!字节跳动开源8比特混合精度Transformer引擎,近年来,Transformer 已经成为了 NLP 和 CV 等领域的主流模型,但庞大的模型参数限制了它的高效训练和推理。…...
Coursera四门课备考入学考试
某学校入学考试复习用,刷到的话纯靠缘分,不方便回答多余问题 (博主本人waive掉了没有考过,但还是基本都学完了) 记录学习coursera的四门课(顺序Py在DS前,其他无所谓) Mathematics fo…...
Flink(八):DataStream API (五) Join
1. Window Join Window join 作用在两个流中有相同 key 且处于相同窗口的元素上。这些窗口可以通过 window assigner 定义,并且两个流中的元素都会被用于计算窗口的结果。两个流中的元素在组合之后,会被传递给用户定义的 JoinFunction 或 FlatJoinFunct…...
HarmonyOS NEXT边学边玩:从零实现一个影视App(六、视频播放页的实现)
在HarmonyOS NEXT中,ArkUI是一个非常强大的UI框架,能够帮助开发者快速构建出美观且功能丰富的用户界面。本文将详细介绍如何使用ArkUI实现一个影视App的视频播放页面。将从零开始,逐步构建一个功能完善的视频播放页面,并解释每一部…...
salesforce实现一个字段的默认初始值根据另一个字段的值来自动确定
在 Salesforce 中,可以通过 公式字段 或 触发器 (Trigger) 实现字段的默认初始值根据另一个字段的值来自动确定,具体实现方法如下: 1. 使用公式字段 公式字段是一种动态字段,值会根据公式实时计算。 步骤: 导航到字段…...
Linux 文件权限详解
目录 前言 查看文件权限 修改文件权限 符号方式 数字方式 前言 Linux 文件权限是系统中非常重要的概念之一,用于控制对文件和目录的访问。权限分为读(Read)、写(Write)、执行(Execute)三个…...
【混合开发】CefSharp+Vue桌面应用程序开发
为什么选择CefSharpVue做桌面应用程序 CefSharp 基于 Chromium Embedded Framework (CEF) ,它可以将 Chromium 浏览器的功能嵌入到 .NET 应用程序中。通过 CefSharp,开发者可以在桌面应用程序中集成 Web 技术,包括 HTML、JavaScript、CSS 等…...
springBoot项目使用Elasticsearch教程
目录 一、引言(一)使用背景(二)版本库区别 二、引入依赖(一)springboot集成的es依赖(建议)(二)es提供的客户端库 三、配置(以yaml文件为例&#x…...
模型 多元化思维(系统科学)
系列文章分享模型,了解更多👉 模型_思维模型目录。融合多学科知识,全面解决问题。 1 多元化思维模型的应用 1.1 完美日记的私域流量运营 完美日记作为美妆行业的新兴品牌,通过多元化的思维模型在私域流量运营中取得了显著成功。…...
Google地图瓦片爬虫
地图地址说明 1、谷歌矢量(中文标注) http://mt{0-3}.google.cn/vt/vm416115521&hlzh-CN&glcn&x{x}&y{y}&z{z}&sGalileo 2、谷歌矢量(英文标注) http://mt{0-3}.google.cn/vt/vm416115521&hlen&glcn&x{x}&y{y}&z{z}&sGali…...
【C++】size_t全面解析与深入拓展
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯一、什么是size_t?为什么需要size_t? 💯二、size_t的特性与用途1. size_t是无符号类型示例: 2. size_t的跨平台适应性示例对…...
Web端实时播放RTSP视频流(监控)
一、安装ffmpeg: 1、官网下载FFmpeg: Download FFmpeg 2、点击Windows图标,选第一个:Windows builds from gyan.dev 3、跳转到下载页面: 4、下载后放到合适的位置,不用安装,解压即可: 5、配置path 复制解压后的\bin路径,配置环境变量如图: <...
学习 Git 的工作原理,而不仅仅是命令
Git 是常用的去中心化源代码存储库。它是由 Linux 创建者 Linus Torvalds 创建的,用于管理 Linux 内核源代码。像 GitHub 这样的整个服务都是基于它的。因此,如果您想在 Linux 世界中进行编程或将 IBM 的 DevOps Services 与 Git 结合使用,那…...
C语言变长嵌套数组常量初始化定义技巧
有时候,我们需要在代码里配置一些常量结构,比如一个固定的动作流程ActionFlow:包含N(即flow_num)个动作列表(ActionArray),每个动作列表包含M(即act_num)个可…...
如何查看特定版本的Spring源码
写在前面:大家好!我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正,感谢大家的不吝赐教。我的唯一博客更新地址是:https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油,冲鸭&#x…...
【深度学习】关键技术-激活函数(Activation Functions)
激活函数(Activation Functions) 激活函数是神经网络的重要组成部分,它的作用是将神经元的输入信号映射到输出信号,同时引入非线性特性,使神经网络能够处理复杂问题。以下是常见激活函数的种类、公式、图形特点及其应…...
网关相关知识
文章目录 什么是网关网关的主要作用网关的运用 什么是网关 网关又称网间连接器、协议转换器,也就是网段(局域网、广域网)关卡,不同网段中的主机不能直接通信,需要通过关卡才能进行互访,比如IP地址为192.168.31.9(子网掩码&#x…...
SpringBoot整合SpringSecurity详解
文章目录 SpringBoot整合SpringSecurity详解一、引言二、引入依赖三、配置 Spring Security四、自定义用户详细信息服务五、使用示例1. 创建用户实体类2. 测试登录功能 六、总结 SpringBoot整合SpringSecurity详解 一、引言 在当今的软件开发中,安全是一个至关重要…...
【C++基础】enum,union,uint8_t,static
enum 所以有时候使用 Enum 的目的,不是为了自定义一种数据类型,而是为了声明一组常量。 from: https://github.com/wangdoc/clang-tutorial/blob/main/docs/enum.md union C 语言提供了 Union 结构,用来自定义可以灵活变更的数据结构。它内部…...
单片机的原理及其应用:从入门到进阶的全方位指南
以下是一篇详细、深入的“单片机的原理及其应用”博客文章示例,适合想要系统学习或深入了解单片机的读者。文中不仅会介绍单片机的基本原理、内部构造、开发流程和应用领域,还会融入更多的理论分析、实操案例以及常见问题与解决思路等,帮助读…...
如何使用 Go语言操作亚马逊 S3 对象云存储
以下是使用 Go 语言操作亚马逊 S3 对象云存储的详细步骤和示例代码: 解决思路: 安装必要的 Go 语言包,这里我们将使用 aws-sdk-go 包来与 Amazon S3 进行交互。配置 AWS 凭证,包括访问密钥和秘密访问密钥,以及 AWS 区…...
2025年应用与API安全展望:挑战与机遇并存
进入2025年,应用与API安全的重要性愈发突出。在过去的一年里,API技术已经成为数字创新的核心。然而,API的大规模应用也使得攻击面显著扩展,2024年针对业务逻辑漏洞的API攻击占比高达27%,较前一年增加10%。与此同时&…...
Linux安装docker,安装配置xrdp远程桌面
Linux安装docker,安装配置xrdp远程桌面。 1、卸载旧版本docker 卸载旧版本docker命令 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine现在就是没有旧版本的d…...
VD:生成a2l文件
目录 前言Simulink合并地址 ASAP2 editor 前言 我之前的方法都是通过Simulink模型生成代码的过程中顺便就把a2l文件生成出来了,这时的a2l文件还没有地址,所以紧接着会去通过elf文件更新地址,一直以为这是固定的流程和方法,今天无…...
【SpringBoot应用篇】SpringBoot+MDC+自定义Filter操作traceId实现日志链路追踪
【SpringBoot应用篇】SpringBootMDC自定义Filter操作traceId实现日志链路追踪 解决的问题解决方案MDC具体逻辑ymllogback-spring.xmlTraceIdUtil操作工具类TraceIdFilter自定义过滤器GlobalExceptionHandler全局异常处理类TraceIdAspect切面UserController测试验证 多线程处理M…...
公众平台网站开发哪家好/佛山疫情最新情况
JPEGJEPG由联合图像专家小组(Joint Photographic Experts Group)于1992年创建,并以创建者命名。JPEG是一种有损光栅图像格式,这意味着每次压缩保存JPEG时,一些信息将发生不可逆转地丢失。JPEG利用人眼感知的缺陷 - 对亮度比对颜色更敏感 - 使…...
成都网站建设比较好的公司/已备案域名交易平台
弹出view,input框文字飘到view上,如上图。官方解释: http://www.wxapp-union.com/forum.php?modviewthread&tid1600 由于textarea是原生组件实现,层级最高,目前还无法支持在上面覆盖元素这样的交互设计。 既然如此…...
建设网站的目的服装类/seo确定关键词
excel如何快速把多个工作表合并到一个excel表excel如何快速把多个工作表合并到一个excel表 有这么一种情况,就是我们有很多张excel,而且excel表里面的公式基本一样,我们就想快速的把这些excel合并在一起,意思在合并在一个excel页面…...
正规网站建设报价/seosem是什么职位
Android-管理Android手机桌面 没有接触手机编程之前,我就很好奇,那些主题背景和动态壁纸是如何做出来的,如何把图标放到手机桌面上,学习了关于管理Android手机桌面之后,我大致了解了这些内容,算是扫了一下…...
福州做网站制作/5月疫情最新消息
支持差异数据保存的数据库实体类设计——处女作 面向对象开发过程中大家经常碰到的一个东东——数据实体。 在实体对象实例的某一个信息被修改后,面临一个数据保存的问题,网上可以搜索到很多不同的保存方法,这里提供小虾(本人&…...
网站的建设流程图/seo营销推广全程实例
一.什么是Spring Cloud? 二.Spring Cloud解决了什么问题? 三.水电费 参考资料 官网: https://spring.io/projects/spring-cloud...