【Linux】编译器gcc/g++、动静态库

【Linux】编译器gcc/g++、动静态库

编译器gcc/g++、动静态库

1.gcc / g++的工作流程

1.编译过程

  1. 预处理:宏替换,取注释,头文件展开,条件编译。
在这里插入图片描述
在这里插入图片描述
  1. 编译:将 C 语言,变成汇编语言。
在这里插入图片描述
  1. 汇编:将汇编语言,变成机器可以识别的代码。
在这里插入图片描述

2.链接过程

链接:将目标文件与一些库链接在一起,生成可执行文件。

在这里插入图片描述

选项:-ESC 对应文件后缀 .iso

3.三大问题

1.如何理解条件编译?

在这里插入图片描述


条件编译的用途?

  1. 软件进行专业度收费情况,使用条件编译进行代码的动态裁剪(免费版在收费版的基础上阉割掉了一些功能)
  2. 内核源代码也是采用条件编译进行代码裁剪。
  3. 开发工具、应用软件等,在不同的平台下(Linux / Windows)都可以运行,只需要一份经过条件编译的代码即可。

2.为什么C/C++编译,要先变成汇编语言?

由于历史发展的原因:

  1. 计算机初期是打孔编程(二进制编程)
  2. 由于打孔编程效率低,接着汇编语言诞生(二进制编写的),这里就需要编译器将汇编语言转化成计算机可以识别的二进制。
  3. 又由于汇编语言写程序还是较为困难,C语言诞生(汇编编写的),这里就需要编译器将C语言转化成汇编语言好呢?还是转化成二进制好呢?答案当然是汇编语言。
  4. 再后来就是:C++/Java/golang/python,都是一个语言编写另一个语言,形成了百家争鸣的场面,若要都转化成二进制,工作量是非常巨大的,干脆站在巨人的肩膀上转化为汇编语言。

3.编译器的发展?

  1. 要发明一门语言,首先需要编译器向下编译成更加低层的语言。
  2. 现在的问题:编译汇编语言成二进制的编译器,是由什么编写的呢?总不能是汇编写的吧!答案:二进制版的编译器,编译汇编语言成二进制。接着用汇编语言写一个汇编编译器,从此以后二进制版的编译器就不用了,诞生了第一个由汇编语言写的编译器来编译汇编语言成二进制。该过程叫做:编译器的自举过程。
  3. 同理C语言也是以上过程。

4.函数库

1.什么是库?

  1. 库是一套方法 / 数据集,为我们开发提供最基本的保证(基本接口,功能),加速我们的二次开发。
  2. 我们的C程序中,并没有定义 “printf” 的函数实现,且在预编译中包含的 “stdio.h” 中也只有该函数的声明,而没有定义函数的实现,那么是在哪里实 “printf” 函数的呢?
  3. 答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中,在没有特别指定时,gcc 会到系统默认的搜索路径 “/usr/lib” 下进行查找,也就是链接到 libc.so.6 函数库中去,这样就能实现函数 “printf” 了,而这也就是链接的作用。
在这里插入图片描述

2.动态库和静态库

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

  1. 静态库是一种将多个目标文件(通常是编译后的代码文件,如 .o 文件或 .obj 文件)打包在一起的文件格式。在编译链接时,链接器会将静态库中的代码直接拷贝到最终的可执行文件中。这意味着每个使用静态库的程序都会有一份库的副本,因此会导致可执行文件较大。
  2. 动态库是一种包含代码和数据的文件,这些代码和数据可以在运行时被多个程序共享。动态库在程序运行时加载到内存中。这意味着多个程序可以共享同一个动态库,从而节省磁盘空间和内存。

动态库和静态库的对比:

  1. 动态库形成的可执行程序体积比静态库小。
  2. 静态库形成了可执行程序后,就不再需要静态库,可执行程序对静态库的依赖度小。动态库不能缺失,否则会导致程序无法执行。
  3. 程序运行需要加载到内存。静态链接,会在内存中出现大量的重复代码。
  4. 动态链接,比较节省内存和磁盘资源。

动态库:Linux(.os文件)Windows(.dll文件)
静态库:Linux(.a文件)Windows(.lib文件)

3.动态链接和静态链接

  1. 动态链接则发生在程序运行时,而不是编译时。当程序启动时,动态链接器(或装载器)会负责将程序所需的动态库(共享库)加载到内存中,并解析程序中的符号引用。与静态链接不同,动态链接允许多个程序共享同一个库文件的代码和数据,从而节省磁盘和内存空间。此外,动态链接还使得程序能够在运行时更新其依赖的库,而无需重新编译整个程序。
在这里插入图片描述
  1. 静态链接发生在程序的编译和链接过程中,当编译器将源代码编译成目标文件后,链接器会将这些目标文件以及所需的静态库合并成一个单一的可执行文件。在这个过程中,链接器会解析所有的符号引用,并将所需的库代码直接嵌入到可执行文件中。因此,静态链接的可执行文件在运行时不再需要额外的库文件,因为它们已经包含了所有必要的代码和数据。
在这里插入图片描述

4.gcc / g++:默认动态链接,使用动态库

gcc

在这里插入图片描述


在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

如何进行静态链接?前提:静态库必须存在,系统默认安装的是动态库,静态库需要自行安装

#CentOS下安装静态库指令sudo yum install -y glibc-static 
在这里插入图片描述
在这里插入图片描述

g++

#下载g++编译器sudo yum install -y gcc-c++ 
在这里插入图片描述
#安装C++静态库sudo yum install -y libstdc++-static 
在这里插入图片描述
在这里插入图片描述

图解

在这里插入图片描述

Linux中的指令大部分都是由C编写的,都需要依赖C动态库,若C动态库被删除了,这些指令都无法使用了。

5.库和链接的本质

在这里插入图片描述

一个场景:不想暴露源文件。

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

Read more

用户选剧情,AI写故事:Trae Solo+GLM-4.6实现沉浸式小说创作体验

用户选剧情,AI写故事:Trae Solo+GLM-4.6实现沉浸式小说创作体验

用户选剧情,AI写故事:Trae Solo+GLM-4.6实现沉浸式小说创作体验 项目背景 在人工智能技术迅猛发展的今天,内容创作正经历从“人工主导”向“人机协同”的深刻变革。传统小说创作往往面临灵感枯竭、结构混乱、节奏把控难等痛点,而现有AI写作工具多为单向输出,缺乏互动性与叙事张力。为打破这一局限,我们打造了一款轻量级、免登录的 AI小说创作平台,旨在通过前沿大模型能力赋能每一位故事创作者。 本项目深度融合 Trae Solo 的高效前端开发与任务调度能力,以及 GLM-4.6 在中文叙事、情节构建和风格一致性上的卓越表现,构建出“用户选剧情,AI写故事”的沉浸式创作闭环。用户只需输入一个故事开头,系统即刻生成三个风格各异的情节分支概览;选定其一后,AI将续写300–500字的高质量正文,并在此基础上持续衍生新分支,形成一棵动态生长的故事树。整个过程无需注册,API Key 通过本地存储安全保存,兼顾隐私与便捷。 平台采用 新粗野主义(

By Ne0inhk
Java 时间类(上):JDK7 及以前时间类 Date、SimpleDateFormat、Calendar 最全总结

Java 时间类(上):JDK7 及以前时间类 Date、SimpleDateFormat、Calendar 最全总结

🏠个人主页:黎雁 🎬作者简介:C/C++/JAVA后端开发学习者 ❄️个人专栏:C语言、数据结构(C语言)、EasyX、JAVA、游戏、规划、程序人生 ✨ 从来绝巘须孤往,万里同尘即玉京 文章目录 * Java 时间类(上):JDK7 及以前时间类 Date、SimpleDateFormat、Calendar 最全总结 🕒 * 📝 文章摘要 * 一、时间相关基础知识点 ⏱ * 1. 时间标准 * 2. 时间单位与换算 * 二、Date 时间类 📅 * 1. 概述 * 2. 构造方法 * 3. 成员方法 * 4. 代码示例 * 三、SimpleDateFormat 格式化与解析 ✍️ * 1. 作用

By Ne0inhk
【Java】从树形结构到二叉树:一篇搞懂数据结构里的“家族树”

【Java】从树形结构到二叉树:一篇搞懂数据结构里的“家族树”

🎁个人主页:User_芊芊君子 🎉欢迎大家点赞👍评论📝收藏⭐文章 🔍系列专栏:Java.数据结构 【前言】 你有没有想过,电脑里的文件分类、通讯录的层级关系,其实都藏着“树”的影子?树形结构是数据结构里最像“现实家族关系”的存在,而二叉树更是其中的“明星选手”——它规则清晰、操作灵活,是很多复杂数据处理的基础。这篇文章会从树形结构的概念入手,一步步拆解二叉树的类型、性质、存储和操作,帮你把这些抽象的结构变成能上手用的知识~ 文章目录: * 一、树形结构 * 1.树形结构的概念 * 2.树的表示形式 * 二、二叉树 * 1.概念 * 2.二叉树类型 * 2.1 满二叉树 * 2.2 完全二叉树 * 3.

By Ne0inhk
Java ForkJoin 框架全面解析:分而治之的并行编程艺术

Java ForkJoin 框架全面解析:分而治之的并行编程艺术

文章目录 * 课程导言 * 适用对象 * 学习目标 * 为什么需要ForkJoin? * 第一部分:核心思想——分治法 + 工作窃取 * 1.1 分治法:从大化小,逐个击破 * 1.2 工作窃取:自动负载均衡的灵魂 * 为什么需要工作窃取? * 工作窃取的实现原理 * 第二部分:ForkJoin框架核心组件 * 2.1 ForkJoinPool —— 任务调度器 * 创建ForkJoinPool * 核心方法 * 2.2 ForkJoinTask —— 任务的抽象 * RecursiveTask<V> —— 有返回值的任务 * RecursiveAction —— 无返回值的任务 * fork() 与 join() 的奥秘 * 2.3 ForkJoinWorkerThread —— 执行任务的工作线程 * 第三部分:实战案例——从入门到精通

By Ne0inhk