坚持用 清晰易懂的图解 + 代码语言,让每个知识点变得简单!
🚀呆头个人主页详情
🌱 呆头个人Gitee代码仓库
📌 呆头详细专栏系列
座右铭: “不患无位,患所以立。”
在这里插入图片描述


《Linux编译器:GCC/G++食用指南》

  • 前言
  • 目录
  • 一、gcc/g++的简单使用
    • 1.作用
    • 2.语法
  • GCC/G++ 编译选项速查表
  • 二、gcc/g++编译器的执行步骤
    • 1.预处理
    • 2.编译
    • 3.汇编
    • 4.链接
    • * 程序执行 *
  • 三、库
    • 1.库的概念
    • 2.库的分类
    • 3 .o与库的链接
    • 4.优缺点
      • **动态库 vs 静态库终极对比表**


前言

🚀 欢迎来到《Linux系统实战》!
这里是命令行到内核的跃迁基地,也是你从"rm -rf恐惧症"到"权限管理大师"的修炼场。

🔍 专栏特色

  • 图解+实战:用最直观的方式拆解Linux核心机制
  • 从应用到底层:覆盖Shell脚本、系统调优、内核模块开发
  • 真实场景:每篇附服务器运维/开发中的实际问题解决方案

💡 学习建议
1️⃣ 先动手尝试(搞崩了也没关系)
2️⃣ 对照文章分析原理
3️⃣ 用文末【实战任务】巩固技能

📌 Linux经典名言
“Linux不是背出来的,是在一次次Permission denied中练出来的!”

(正文开始👇)


目录

一、gcc/g++的简单使用

1.作用

gcc和g++分别是GNU的C和C++的编译器,gcc和g++在执行编译的时候一般有以下四个步骤:
1)预处理(头文件展开、去注释、宏替换、条件编译)。
2)编译(C代码翻译成汇编语言)。
3)汇编(汇编代码转为二进制目标代码)。
4)链接(将汇编过程产生的二进制代码进行链接)。

2.语法

GCC/G++ 编译选项速查表

选项功能说明备注
-E只进行预处理,不生成文件需手动重定向到输出文件(如 gcc -E test.c > test.i
-S编译到汇编语言(生成 .s 文件),不进行汇编和链接保留预处理 + 编译结果
-c编译到目标代码(生成 .o 文件),不链接适用于分步编译
-o <file>指定输出文件名gcc test.c -o test
-static强制静态链接(生成文件较大)优先链接静态库而非动态库
-g生成调试信息(GDB 可用)默认生成 release 版本需显式添加此选项
-shared生成动态链接库(.so 文件)通常配合 -fPIC 使用
-w禁用所有警告信息不推荐使用(可能掩盖潜在问题)
-Wall开启所有标准警告信息实际不包括所有警告(建议结合 -Wextra
-O0不优化(调试时推荐)保留原始代码结构
-O1基础优化(默认级别)在编译速度和性能间平衡
-O2深度优化(推荐发布使用)包含大多数安全优化选项
-O3激进优化(可能增加代码体积)可能改变程序行为(需严格测试)

小技巧

  • 组合使用示例:g++ -Wall -O2 -g main.cpp -o app
  • 查看完整选项:gcc --helpman gcc

二、gcc/g++编译器的执行步骤

gcc和g++的执行步骤中的指令都是相同的,这里小编以linux中的gcc编译器的执行步骤中的指令为例进行讲解

1.预处理

预处理功能主要包括宏定义,文件包含,条件编译,去注释等。

  • 预处理指令是以#号开头的代码行。
  • 实例: gcc –E hello.c –o hello.i
  • 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
  • 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序。
    在这里插入图片描述
  1. 去掉注释
    注释是写给开发者人员的自然对于程序的编译自然无用,所以编译器将对于编译阶段无用的注释去掉
  2. 头文件的展开
    头文件既然可以进行展开,那么说明在系统路径下一定有地方存放头文件,在预处理阶段将头文件的内容拷贝到源文件中
  3. 条件编译
    可以支持对代码的裁剪工作,例如应用的社区版和免费版其实就是应用了条件编译,使同一份代码经过条件编译后呈现出两种不同的状态
  4. 宏替换
    特别讲解一下这里的宏替换不进行语法检查,我们知道在编译阶段进行语法的检查,而宏替换是在编译阶段之前,即预处理阶段已经完成了宏替换,即预处理完之后由于宏已经被替换了,所以此时宏就没有了,自然在进行编译阶段不进行宏替换的语法检查。

在这里插入图片描述

2.编译

gcc -S code.i -o code.s

gcc -S 要进行编译的文件名(建议使用预处理后以 .i 为后缀的文件) -o 编译后的文件名(这里建议使用 .s 为后缀),即告诉编译器从现在开始进行翻译,当编译工作完成后,就停下来
在这里插入图片描述

  • 在这个阶段中,gcc/g++首先检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,将代码翻译成汇编语言。
  • 用户可以使用-S选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
  • -o选项是指目标文件,“xxx.s”文件为已经过翻译的原始程序。
    在这里插入图片描述

3.汇编

gcc -c code.s -o code.0

gcc -c 要进行汇编的文件名(这里建议使用编译后的.s文件) -o 汇编后的文件名(这里建议使用.o为后缀的文件名),告诉编译器开始进行程序的翻译,当汇编工作完成后,就停下来
在这里插入图片描述

  • 汇编阶段是把编译阶段生成的“xxx.s”文件转成目标文件。
  • 使用-c选项就可以得到汇编代码转化为“xxx.o”的二进制目标代码了。
    在这里插入图片描述

4.链接

gcc code.o -o code

gcc 要进行链接的文件(这里建议使用执行完汇编后生成的.o文件) -o 链接后的文件名,将编译生成的可重定位目标二进制文件(目标文件)和库进行链接生成可执行程序
在这里插入图片描述

  • 在成功完成以上步骤之后,就进入了链接阶段。
  • 链接的主要任务就是将生成的各个“xxx.o”文件进行链接,生成可执行文件。
  • gcc/g++不带-E、-S、-c选项时,就默认生成预处理、编译、汇编、链接全过程后的文件。
  • 若不用-o选项指定生成文件的文件名,则默认生成的可执行文件名为a.out。
    在这里插入图片描述
    注意: 链接后生成的也是二进制文件。

* 程序执行 *

./可执行文件名,即可执行可执行文件
在这里插入图片描述

三、库

1.库的概念

  • 在链接的时候会进行汇编生成的二进制文件和库进行链接,那么这个库具体是指的是什么呢?
  • 拿c语言程序中的printf函数来说,在程序中调用printf打印hello,#include <stdio.h>头文件中是printf函数的声明,那么实现究竟是在哪里呢?没错,在库中,
  • 在库中提供函数方法的实现,在c语言中即为c语言标准库
    库的本质是文件,有其对应的路径在linxu中为(动态库)/usr/lib64/libc.so或(静态库)/usr/lib64/libc.a

2.库的分类

  1. linux:.so(动态库) .a(静态库)
  2. windows:.dll(动态库) .lib(静态库)
  3. 系统默认只提供动态库,为/usr/lib64/libc.so,但是对于静态库/usr/lib64/libc.a系统默认不提供即没有进行安装,这时候我们就要自行去安装静态库或动态库

动态库

# 安装运行时库(仅动态库,无头文件)
sudo yum install curl# 安装开发包(包含头文件和动态库链接)
sudo yum install libcurl-devel

在这里插入图片描述
静态库

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

在这里插入图片描述

方法的实现其实就在库中
库其实是将源文件经过翻译,打包成为一个文件(不用提供太多的源文件,也达到了隐藏源文件的目的),库避免了一些经常性使用的函数实现的重复书写,节省工作,提高效率
你的软件=头文件提供声明+库提供函数的实现+你的代码

3 .o与库的链接

库分为动态库(共享库)和静态库,那么对应有动态链接和静态链接
动态链接:

  1. 动态链接是在程序执行时由运行时的链接文件加载库,所以很多程序的运行都要依赖动态库的存在,所以动态库不能缺失,一旦缺失会造成很多程序无法运行,进而可能造成无法使用操作系统
  2. 静态链接:
    编译器在使用静态库进行静态链接的时候,会将静态库的方法拷贝到目标程序中,需要使用哪些函数方法就将哪些函数方法拷贝到目标文件中,并不是将静态库的所有方法都拷贝到目标文件中,这一点经常被混淆,请读者友友们注意区分,此后程序的执行不再需要依赖静态库在linux中,编译形成可执行程序,默认采用的链接方式是动态链接—动态库

ldd 可执行程序 可以查看或打印一个程序运行所需的共享库
在这里插入图片描述

观察一下静态链接方式由于是将库进行拷贝,所以占用空间明显大于动态链接(程序执行时由运行的链接文件进行加载库)方式在这里插入图片描述

  • 如果没有静态库,我们不能使用-static进行静态链接
  • 如果没有动态库,只有静态库,并且编译器gcc可以找到静态库,此时编译器采用静态链接将我们的目标文件和库进行链接,因为当系统中存在动态库的时候,系统会优先采用动态链接,当不存在动态库的时候,编译器会再去看看系统中有没有静态库,如果有静态库则采用静态链接的方式,如果连静态库都没有则报错
  • 同时在我们的可执行文件中,并不是所有的链接方式都是纯动态链接的,而是动态链接和静态链接混合的方式
  • file 可执行程序,可以查看我们的可执行程序的链接方式
    在这里插入图片描述

4.优缺点

以下是符合 CSDN 博客风格的 Markdown 表格,对比动态库和静态库的优缺点,并优化了可读性和技术专业性:


动态库 vs 静态库终极对比表

特性动态库(.so/.dll)静态库(.a/.lib)
🔧 编译方式编译时记录依赖,运行时加载编译时直接嵌入到可执行文件中
📦 文件体积✅ 极小(仅记录符号)
• 多个程序共享同一份库文件
❌ 巨大(库代码直接复制到程序)
• 每个程序都包含完整库代码
🏃 运行依赖❌ 必须存在
• 缺失时报错:error while loading shared libraries
✅ 完全独立
• 单文件即可运行
🔄 更新维护✅ 热更新
• 替换 .so 文件立即生效
❌ 需重新编译
• 修复库=重新发布所有程序
⚡ 运行性能⚠️ 略慢(首次加载需解析符号)✅ 极致快(无运行时链接开销)
💣 兼容性❌ 地狱级难题
glibc 版本冲突常见
✅ 无烦恼
• 库和程序成绑定关系
🛡️ 安全性⚠️ 有风险
• 可能被恶意替换成钓鱼库
✅ 铁布衫
• 代码全内嵌防篡改
🚀 适用场景• 桌面应用(如WPS)
• 微服务容器
• 插件系统(如Nginx模块)
• 嵌入式设备
• 路由器固件
• 安全敏感工具(如tcpdump
💻 部署难度❌ 需处理依赖树
LD_LIBRARY_PATH/rpath 配置复杂
✅ 双击即用
• 无环境依赖

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

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

相关文章

SparkKV转换算子实战解析

目录 KV算子 parallelizePairs mapToPair mapValues groupByKey reduceByKey sortByKey 算子应用理解 reduceByKey和groupByKey的区别 groupByKeymapValues实现KV数据的V的操作 改进用reduceByKey groupby通过K和通过V分组的模板代码 问题集锦 宝贵的经验 这里会…

深度解析 TCP 三次握手与四次挥手:从原理到 HTTP/HTTPS 的应用

TCP 的三次握手和四次挥手是网络通信的基石&#xff0c;无论是 HTTP 还是 HTTPS&#xff0c;它们都依赖 TCP 提供可靠的传输层服务。本文将用万字篇幅&#xff0c;结合 Mermaid 图表和代码示例&#xff0c;深入讲解 TCP 三次握手、四次挥手的原理、过程、状态变化&#xff0c;以…

Hyper-V + Centos stream 9 搭建K8s集群(一)

一、创建虚拟机一台32G内存&#xff0c;16核心的Win11&#xff0c;已经安装了Hyper-V 管理器。然后也下载了CentOS-Stream-9-latest-x86_64-dvd1.iso的镜像文件。这里Hyper-V创建虚拟机的过程就不赘述了&#xff0c;如果出现虚拟机加载不到镜像的问题&#xff0c;先把这个使用安…

Pygame如何制作小游戏

以下是 Pygame 的详细使用指南&#xff0c;从安装到开发完整游戏的步骤说明&#xff0c;包含代码示例和最佳实践&#xff1a; 一、安装与环境配置 1. 安装 Pygame pip install pygame2. 验证安装 import pygame pygame.init() print(pygame.version.ver) # 应输出版本号&am…

@【JCIDS】【需求论证】联合能力集成与开发系统知识图谱

JCIDS(联合能力集成与开发系统)知识图谱 1. JCIDS概述 2. JCIDS的提出背景 3. JCIDS核心流程 4. JCIDS分析方法 5. JCIDS优势 6. JCIDS与采办系统的关系 7. JCIDS知识图谱结构 8. 对我的启示 9.JCIDS(联合能力集成与开发系统)相关术语列表 10. 参考文献 1. JCIDS概述 定义:…

每天学一个Linux命令(38):vi/vim

每天学一个 Linux 命令(38):vi/vim vi 和 vim(Vi IMproved)是 Linux 和 Unix 系统中功能强大的文本编辑器。vim 是 vi 的增强版,提供语法高亮、多级撤销、插件支持等更多功能。掌握 vi/vim 是 Linux 系统管理员的必备技能之一。 1. 命令简介 vi:经典的文本编辑器,几乎…

【PZ-ZU49DR-KFB】:璞致电子 UltraScale+ RFSoC 架构下的软件无线电旗舰开发平台

璞致电子 PZ-ZU49DR-KFB 开发板基于 Xilinx ZYNQ UltraScale RFSoC XCZU49DR 主控制器&#xff0c;以 "ARMFPGA 异构架构" 为核心&#xff0c;融合高带宽信号采集、高速数据处理与灵活扩展能力&#xff0c;专为专业工程师打造的软件无线电&#xff08;SDR&#xff09…

力扣106:从中序与后序遍历序列构造二叉树

力扣106:从中序与后序遍历序列构造二叉树题目思路代码题目 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 思路 我们首先要知道中序遍历和后序…

IDEA JAVA工程入门

Maven配置&#xff1a; IDEA -> settings -> Build, Execution, Deployment -> Build Tools -> MavenMaven home pathUser setting file : 特定仓库下载依赖包&#xff0c;自动下载(界面右边M图标点开&#xff0c;)local repository &#xff08;本地仓库&#xff…

Spring依赖注入:从原理到实践的自学指南

Spring依赖注入&#xff1a;从原理到实践的自学指南 一、什么是依赖注入&#xff1f; 依赖注入&#xff08;Dependency Injection, DI&#xff09;是Spring框架实现控制反转&#xff08;IoC&#xff09;的核心手段。其核心思想是&#xff1a;对象不再自己创建依赖项&#xff…

3_软件重构_组件化开发实例方法论

1、上期回顾上次内容核心的地方有两个&#xff0c;①是C多态基类的指针指向派生类&#xff0c;用于初始化各个插件。②是使用C语言的dlopen函数“动态加载”各个插件&#xff0c;实现用户根据契约接口自定义开发插件&#xff0c;极大程度地实现了软件上的解耦。③再进一步&…

C#接口的定义与使用

第1章 接口&#xff08;interface&#xff09;是什么1.1 定义• 接口是一组“能力”或“契约”的抽象描述&#xff0c;只规定“能做什么”&#xff0c;不规定“怎么做”。• 在 C# 中&#xff0c;接口是一种完全抽象的类型&#xff08;fully abstract type&#xff09;。 • 关…

【STM32】HAL库中的实现(三):PWM(脉冲宽度调制)

&#x1f527; HAL库中的实现&#xff1a;PWM&#xff08;脉冲宽度调制&#xff09; PWM&#xff08;Pulse Width Modulation&#xff09;是基于定时器&#xff08;TIM&#xff09;产生的周期性脉冲信号&#xff0c;广泛应用于&#xff1a;① 电机调速&#xff1b;② LED 亮度控…

GitHub 趋势日报 (2025年08月03日)

&#x1f680; GitHub 趋势日报 (2025年08月03日) &#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图751dyad362LLMs-from-scratch291…

Java后端高频面试题

Java后端高频面试题 目录 Java集合框架Java并发编程JVM相关MySQL数据库Redis缓存Spring框架 Java集合框架 HashMap的数据结构是什么&#xff0c;为什么在JDK8要引入红黑树&#xff1f; HashMap数据结构&#xff1a; JDK7&#xff1a;数组 链表JDK8&#xff1a;数组 链表…

37. line-height: 1.2 与 line-height: 120% 的区别

概述 line-height 是 CSS 中用于控制文本行间距的重要属性。虽然 line-height: 1.2 和 line-height: 120% 看似相同&#xff0c;但它们在计算方式上存在关键区别&#xff0c;尤其是在继承和计算值方面。1. 计算方式不同写法类型计算方式说明line-height: 1.2无单位&#xff08;…

蓝桥杯----DS1302实时时钟

&#xff08;六&#xff09;、DS1302实时时钟1、原理&#xff08;图 二十六&#xff09;DS1302通过三线串行接口与单片机进行通信。微控制器可以通过设置RST引脚为高电平来使能DS1302&#xff0c;并通过SCK引脚提供串行时钟信号&#xff0c;然后通过I/O引脚进行数据的读写操作。…

C++对象访问有访问权限是不是在ide里有效

在C中&#xff0c;对象的访问权限&#xff08;即公有&#xff08;public&#xff09;、保护&#xff08;protected&#xff09;和私有&#xff08;private&#xff09;成员的访问&#xff09;是编译时的一部分&#xff0c;而不是运行时。这意味着&#xff0c;无论是在IDE&#…

CubeMX安装芯片包

1.点击HELP2.选择公理嵌入式软件包3.选择并下载芯片包

【面向对象】面向对象七大原则

设计模式 设计模式是什么&#xff1f; 设计模式是一种针对于反复提出问题的解决方案&#xff0c;是经过长时间经验和试错而总结出来的一套业务流程&#xff1b; 其目的是为了提高代码的可重用性和可维护性&#xff0c;让代码更容易让人理解&#xff0c;保证代码可靠性&#…