自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(43)
  • 收藏
  • 关注

原创 【Linux】动静态库

我们在使用ldd命令时,可以看到我们可执行程序所依赖的标准库,说明系统应该默认会去标准库路径(/lib64)下查找我们所使用到的库,那么我们想要系统或加载器能识别到我们自己的库,是不是只要把我们自己的库文件和头文件拷贝到标准路径下就可以了呢?我们通过-I、-L以及-l选项是在告诉编译器我们的库文件和头文件所在位置,我们的系统并不知道,当我们的程序编译链接形成可执行文件时,已经和编译器没有关系了,所以我们的系统去找库的时候找不到我们自己的库。结果是会报错找不到库,我们静态链接的前提是必须有静态库。

2025-10-19 12:56:06 568

原创 【Linux】动态链接和动态加载

内核:你在Shell中输入 ./my_program 后,内核的加载器首先工作。它读取ELF文件头,发现这是一个动态链接的可执行文件(因为包含INTERP 段)。内核为进程创建虚拟地址空间,并将程序本身的代码段(.text)、数据段(.data)等LOAD 段映射到内存中。内核根据INTERP 段指定的路径,将动态链接器(例如 /lib64/ld-linux-x86-64.so.2)这个特殊的共享库加载到内存。内核不执行程序的 _start,而是直接将控制权跳转到动态链接器的入口点。

2025-10-14 10:37:03 771

原创 【Linux】理解链接过程

ELF文件中的每个LOAD类型Segment(需要加载的段)在程序加载时,都会在内核中创建一个对应vm_area_struct结构体,该结构体继承了Segment的虚拟地址范围、访问权限和文件偏移等关键信息,成为该段内存在内核中的运行时管理单元。这里的两次call就是指我们调用了两次函数(printf 和 run),前面的数字e8其实就是用十六进制代表call命令,后面跟着的一串零其实应该是调用的函数地址(暂时为0),因为此时编译器是不知道函数地址的,和其他的模块链接后才知道函数地址。

2025-10-12 18:30:19 753

原创 【Linux】认识ELF格式文件

ELF(Executable and Linkable Format)是Linux系统中可执行文件(.exe)、目标文件(.o)、共享库(.a)和核心转储的标准文件格式。ELF头(ELF Header):描述文件的基本属性,如目标架构、入口地址、段头表和节头表的位置程序头表(Program Header Table):列举了所有有效的段(segments)和他们的属性。

2025-10-09 20:23:49 678

原创 Ext2文件系统

当需要读写大量连续数据时,如果数据都存储在同一个柱面上,硬盘就可以在第一个盘面读写完后,无需移动磁头臂,直接切换到第二个盘面的磁头继续读写,然后再切到第三个...这样大大减少了磁头寻道的时间,极大地提高了读写速度。有时候编译项目时,我们可能会访问几百个文件,如果我们每次访问文件都要做一次完整的路径解析,而路径解析需要读取磁盘上的目录内容,那就意味着要做很多次磁盘访问,磁盘I/O操作比内存操作慢数万倍!如果这个文件时目录文件的话,那么就存储的是目录的结构信息(即文件名到 inode 号的映射关系)。

2025-10-04 20:43:04 954

原创 【Linux】基础 I/O

打开文件的方式不仅仅是fopen,ifstream等流式,语言层的方案,其实系统才是打开文件最底层的方案,fopen、fwrite...都是封装的系统文件。这是因为我们把1号文件描述符重定向到普通的磁盘文件中,刷新方式从行缓冲变成了全缓冲,我们写的内容肯定没有装满缓冲区,所以没有刷新,此时我们可以手动刷新一下,就可以让内容刷新出来了。这里我们重新写了一个重定向的文件,本来是想实现和前面一样的功能,将printf打印的内容打印到log.txt文件中,但是这里我们什么都没看到,这是为什么呢?

2025-09-30 15:01:28 782

原创 【Linux】再识进程(Ⅱ)

父进程需要知道子进程的终止状态(比如它是正常退出还是被信号杀死的,退出码是多少),否则子进程可能会变成“僵尸进程”,占用系统资源导致资源的浪费。理解 exec 最关键的一点是:它并不创建新的进程,而是将当前进程的内存空间(包括代码、数据、堆栈等)完全清空,然后加载并执行一个新的程序文件,所以进程的id并不改变。:创建一个新的进程(子进程),子进程是父进程的副本,拥有和父进程相同的代码、数据段(若读写数据:写时拷贝)、堆栈等。进程终止的本质是释放系统资源,释放进程申请的相关内核数据结构和对应的数据和代码。

2025-09-26 14:00:20 1452

原创 【Linux】初识进程(Ⅰ)

冯诺依曼体系的核心思想就是存储思想:计算机的程序和程序所处理的数据一样,都以二进制的形式存储在同一个存储器中。功能: 负责执行所有的算术运算和逻辑运算。例子: 加减乘除、与或非比较等操作。功能: 是整个计算机的指挥中心。它从存储器中读取指令,进行分析,然后向其他部件发出控制信号,协调各部件步调一致地工作。运算器 + 控制器 = 中央处理器,也就是我们常说的 CPU。功能: 用于存放程序和数据。所有信息(指令和数据)都以二进制形式存储在此。

2025-09-22 19:36:08 981

原创 Linux开发者三剑客:git、gdb、cgdb

目录1. 下载git/gdb/cgdb2. 认识git/gdb/cgdb2.1 git2.1.1 创建项目2.1.2 git三板斧2.2 gdb2.3 cgdb3. gdb/cgdb的基本操作3.1 操作总结这个命令大家可以直接AI,下面是我用Deepseek生成的,大家直接根据自己的系统下载就行,有问题也可以问AI。git 是一个开源的分布式版本控制系统(Distributed Version Control System, DVCS)。它由 Linus Torvalds 为管理 Linux 内核开发而创

2025-09-16 09:25:02 717

原创 【C++】C++11介绍(Ⅱ)

C++98设计的一个智能指针叫 auto_ptr ,它的特点是在拷贝时把被拷贝对象的资源管理权交给拷贝对象,但这样可能会使被拷贝对象悬空,从而报错。默认生成的移动构造/移动赋值重载,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。如果你没有实现移动赋值重载函数,且没有实现析构函数、拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。是一个通用的函数包装器,可以存储、复制和调用任何可调用对象。

2025-09-13 19:28:00 866

原创 【C++】C++11介绍(Ⅰ)

定义:能够出现在赋值运算符左侧的表达式,代表一个可标识的内存位置(有明确的存储地址),可以被修改或取地址。特点具有持久性(在内存中占据一定空间,生命周期较长)可以被赋值可以使用运算符取地址。

2025-09-12 09:15:01 1078

原创 【C++】用哈希表封装unordered_XX

所以相同的内容我就不再赘述了,本篇主要就是展示一下大致思路,代码部分偏多,大家可以一起试试实现一下哦!

2025-08-26 21:27:04 414

原创 【Linux】编辑器vim的使用

我们可以直接用键盘上的光标来上下左右移动,但正规的vim是用写英文字母「h」、「j」、 「k」、「l」,分别控制光标左、下、上、右移⼀格。• 「#」:「#」号表示⼀个数字,在冒号后输入⼀个数字,再按回车键就会跳到该行了,如输入数字 15,再回车,就会跳到文章的第15行。• 「/关键字」:先按「/」键,再输入想寻找的字符,如果第⼀次找的关键字不是想要的,可以 ⼀直按「n」会往后寻找到您要的关键字为止。」键,再输入想寻找的字符,如果第⼀次找的关键字不是想要的,可 以⼀直按「n」会往前寻找到您要的关键字为止。

2025-08-15 13:05:11 1278

原创 【C++】哈希表的实现

当key是string/Date等类型时,key不能取模,那么我们需要给哈希表增加⼀个仿函数,这个仿函数支持把key转换成⼀个可以取模的整形,如果key可以转换为整形并且不容易冲突,那么这个仿函数就用默认参数即可,如果这个key不能转换为整形,我们就需要自己实现⼀个仿函数传给这个参数,实现这个仿函数的要求就是尽量key的每个值都参与到计算中,让不同的key转换出的整形值不同。当负载因子超过某个阈值(通常为0.7-0.8,下面代码实现用的是0.7)时,哈希表的性能会显著下降,此时需要进行扩容操作。

2025-08-13 20:05:28 587

原创 【Linux】关于权限的概念

注:但实际上所创建的文件和目录权限往往不是你上面设置的,因为创建文件或目录的时候还会收到umask的影响。假如默认权限是mask,但实际创建的文件权限是:mask&~umask。写(w—write):对文件来说,修改文件的权限;读(r—read):对文件来说,读取文件内容的权限;执行(x—execute):对文件来说,执行文件的权限;文件和文件目录的所有者所在组的用户:g --- Group。注:只有文件的拥有者和roo才可以改变文件的权限。- : 向权限范围取消权限代号所表示的权限。

2025-08-12 09:04:24 395

原创 【C++】map和set的封装

因为map和set的元素类型不同,所以在比较大小时,所依据的key表示方法就不一样,为了解决这个问题,我们使用一个KeyOfT的类型来解决这个问题。前面我们已经实现了红黑树,直接将我们实现的红黑树拿过来使用,各位可以先看一下小编下面这篇博客内容,再和这篇文章联系起来。在map和set中key值都是具有唯一性的,所以我们需要保证key不能被修改,这个问题可以用const来解决。最后就是实现map中的 [ ] 功能。在map和set中直接套用就可以了。

2025-08-11 08:00:00 428

原创 【C++】红黑树实现

红黑树(Red-Black Tree)是一种自平衡的二叉搜索树,通过特定的规则确保树的高度始终保持在对数范围,从而保证插入、删除、查找等操作的时间复杂度为 O(log n)。

2025-08-06 14:32:56 403

原创 【C++】AVL树实现

AVL树是一种自平衡的二叉搜索树(BST),由G.M. Adelson-Velsky和E.M. Landis在1962年发明,是最早的自平衡二叉搜索树之一。AVL树在二叉搜索树的基础上增加了一个平衡条件:对于树中的任意节点,其左子树和右子树的高度差不超过1。这个高度差称为平衡因子(Balance Factor)。

2025-08-03 02:15:43 735

原创 【C++】set基本用法

通常 set 是用红黑树(一种自平衡二叉查找树)实现的,这保证了高效的查找、插入和删除操作。:set 中的元素总是按照特定的排序准则自动排序,默认是升序排列。:set 中的每个元素都是唯一的,不允许重复。

2025-07-29 01:32:37 325

原创 【Linux】基础指令(Ⅲ)

r 递归处理,将指定目录下的所有文件和子目录一起压缩。将../show/test.tar.gz目录下的文件解压缩到当前文件。语法:zip 选项 压缩包名.zip 目录/文件。:指定文件名,f后面直接跟文档名,不要加别的选项。-d 指定解压目录(默认当前目录)语法:whereis 命令名/二进制文件。用于在目录树中根据指定条件查找文件或目录。-a 全部信息,综合以上所有信息。语法:find 选项 文件/目录。语法:tar 选项 文件/目录。

2025-07-28 14:06:24 476

原创 【C++】map基本用法

C++ 标准模板库(STL)中的关联容器,它存储的元素是键值对(:查找、插入、删除操作的时间复杂度为 O(log n):元素按照键(key)的升序自动排序。:内部通常实现为红黑树,保证操作效率。:每个键只能出现一次。

2025-07-21 15:17:41 458

原创 【C++】二叉搜索树

二叉搜索树(Binary Search Tree, BST)是一种二叉树数据结构,其中每个节点的值都大于其左子树中所有节点的值,且小于其右子树中所有节点的值。这一性质递归地适用于所有子树,使得中序遍历BST会得到一个严格升序的序列。如下图:这就是一个简单的二叉搜索树。

2025-06-07 17:14:27 477

原创 【C++】多态

●必须是基类指针或者引用调用虚函数●被调用的函数必须是虚函数,并完成了虚函数的重写/覆盖。

2025-06-01 19:50:30 953

原创 【C++】继承

注意:派生类的operator=隐藏了基类的operator=,所以显示调用基类的operator=,需要指定基类作用域。1. public继承的派生类对象可以赋值给基类的指针/基类的引用。引用的是派生类中基类的部分,所以这个过程也有个形象化的叫法:切片或者切割。1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。一种特殊的多继承情况,形成菱形结构的继承关系。

2025-05-17 21:09:10 754

原创 【Linux】基础指令(Ⅱ)

与more类似,但less可以随意浏览文件,而more仅能向下(前)移动,却不能向上(后)移动,而且less在查看之前不会加载整个文件。该指令相当于输出命令,可以直接输出内容,也可以借助输出重定向符号,将内容输出到指定文件内,如果文件不存在就直接生成一个新文件。-n 规定输出行数,按向下键就会n行n行的输出,直到输出完文件中的内容就能自动退出,或者按q直接退出。用来显示开头或结尾某个数量的文字区块,head用来显示档案的开头至标准输出中,而tail就是看档案的结尾。

2025-05-14 21:01:17 876

原创 【C++】模版详解

我们在实现功能相似但数据类型不同的函数或者类时,往往要写好几个相似的函数或者类,模版就可以先给我们提供一个框架,然后在编译时根据需要的类型使用这个框架。常用的模版有函数模版和类模版。一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有 目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。

2025-05-09 20:06:52 1059 1

原创 【Linux】基础指令(Ⅰ)

本篇示例使用的都是红帽Linux系统。

2025-05-06 21:17:00 921

原创 【C++】stack和queue的底层实现

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设 计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。:STL 的 stack 和 queue 不是独立的容器,而是"适配器",它们基于现有容器(默认deque)提供特定接口。deque 支持高效的头部和尾部操作(O(1)时间复杂度)不需要像 vector 那样频繁扩容。内存使用比 list 更紧凑。

2025-05-05 19:55:12 290 1

原创 【C++】priority_queue底层实现

通过手动实现优先队列,我们可以深入理解:优先队列的基本操作仿函数在模板设计中的重要性这种底层实现的分析不仅帮助我们更好地使用标准库提供的优先队列,也为需要自定义优先级逻辑的场景提供了基础。

2025-05-04 20:30:00 382

原创 【C++】My_list实现

通过手动实现list,我们可以深入理解:双向链表的基本结构和操作迭代器如何封装底层指针操作STL容器的设计哲学模板编程在容器设计中的应用这种实现虽然简化,但涵盖了list的核心思想和关键实现技术。理解这些底层实现有助于我们更有效地使用标准库容器,并在需要时实现自定义的容器类型。希望本文能帮助你深入理解C++ list的底层实现原理!

2025-05-03 16:52:07 463

原创 【数据结构】七大排序算法

通过一段代码,比较这几个排序算法排序随机的N个数据大小所需时间i < N;free(a2);free(a3);free(a4);free(a5);free(a6);free(a7);

2025-05-01 20:58:42 634

原创 【C++】vector的基本操作实现

Vector 是 C++ STL 中最常用的顺序容器之一,它提供了动态数组的功能,能够自动管理内存并在运行时动态增长。本文将结合标准库实现和我自己实现的简化版 Vector,深入探讨 Vector 的内部机制。vector/vector/vector.h · 大白同学/C++的学习 - Gitee.com。

2025-04-25 14:04:58 400

原创 【C++】string的底层实现

按照自己的理解实现了一下string的一些功能,主包自己弄的可能没有很规范,欢迎大家提出修改建议。

2025-04-22 10:51:11 162

原创 【C++】string详解

深拷贝不仅复制对象本身,还复制对象所拥有的所有资源,新旧对象拥有各自独立的资源副本。浅拷贝只复制对象本身,而不复制对象所指向或包含的资源,新旧对象共享相同的资源。

2025-04-18 15:44:23 970

原创 C++——类与对象(Ⅲ)

初始化列表是构造函数的一种初始化方式,使用方法是以一个冒号开始,接着是一个以逗号分割的数据成员列表,在每个“成员变量”后面跟一个放在括号中的初始值或表达式。用static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针,所以不能访问非静态的成员变量,只能访问静态的;引用成员变量,const成员变量,没有默认构造的类类型变量,必须放在初始化列表位置进行初始化,否则会编译报错。友元函数声明可以再类的任何地方,不受类访问限定符的限制,但是习惯上,一般放在类中最上面的地方。

2025-03-15 18:29:32 846

原创 C++——类和对象(Ⅱ)

默认成员函数就是用户没有显示实现,编译器会自动生成的成员函数。一个类中,我们不写的情况下,编译器会默认生成下面几个默认成员函数。

2025-03-03 11:10:00 1118

原创 C++——类与对象(Ⅰ)

class是定义类的关键字,后面紧接着是类的名字,{}中是类的主体。类中的变量称为类的属性或成员属性;类的函数称为类的方法或者成员函数。●为了区分成员变量,一般习惯上成员变量前面或者后面会加一个_或者m,但这并不是强制的。C++中struct也可以定义类,C++兼容C中struct的用法,同时升级成了类,所以C++中的struct中可以定义函数,通常我们还是使用class定义类。定义在类中的成员函数默认为inline。

2025-02-11 15:20:05 368

原创 VS2022实用调试技巧

在计算机中,bug是指软件程序中的漏洞或缺陷。这些漏洞和缺陷可能会导致程序崩溃,输出错误或者其他异常现象。为了预防和解决bug,开发人员应该遵循良好的软件工程实践和代码规范,并进行充分的测试和调试。调试是发现和减少计算机程序中程序错误的一个过程。它包括识别问题、隔离问题源,然后纠正问题或确定解决问题的方法,并最终测试修正以确保系统正常运行。调试在‌软件开发和维护中起着至关重要的作用。通过调试,可以及时发现和解决隐藏的错误,提高软件的质量和稳定性。

2024-11-20 16:19:02 838

原创 C++关键字namespace

在给变量命名时,要避免出现冲突,因此如何给变量命名都是程序员比较头疼的问题,而C++中的关键字namespace就是用来解决这个问题的。

2024-11-19 01:33:24 411

原创 C语言中数据的表现形式及其运算符(Ⅱ)

有时,用户的输入可能不符合预定的格式。只要把*加在任何占位符的%后面,该占位符就不会返回值,解析后就会被丢弃。为了方便编写代码,C语言还提供了许多复合赋值符,如:+=,-=,*=,/=,%=,<<=,>>=,&=,|=,^=(后面五个属于位运算,但是复合赋值符的运算规则都是相似的)俗话说,强扭的瓜不甜,强制类型转换也是如此,强制转换数据类型有时会导致数据的缺失,所以一般情况,不建议使用强制类型转换。程序运行到这个语句时,程序会停下来,等用户输入数据、按下回车键后,函数就会开始处理数据,将数据存储到变量中。

2024-09-28 00:58:58 314

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除