自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 数据在内存中的存储,大小端

超过一个字节的数据在内存中存储的时候,就有存储顺序的问题,我们要怎样在内存中存放数据呢。按照乱序正序还是倒序呢?计算机只采取了两种方式,按照不同的存储顺序,我们分为大端字节序存储和小端字节序存储。数据的低位存在高地址称为大端字节序存储。数据的低位存在低地址称为小端字节序存储。如图正在写博客的这台电脑就是小端存储。因为位于低位的01存放在了低地址0x003EFD34。为什么会有大小端模式之分呢?

2024-04-28 18:12:04 770

原创 C语言内存函数及模拟实现

函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。这个函数在遇到’\0’ 的时候并不会停下来。如果source和destination有任何的重叠,复制的结果都是未定义的。for (i = 0;i < 10;从 str2 复制 n 个字符到 str1,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。

2024-04-28 16:32:33 389 1

原创 字符串函数及其模拟实现

函数介绍:字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’)。参数指向的字符串必须要以’\0’ 结束。注意函数的返回值为size_t,是无符号的实现字符串拷贝,左参数是目标字符串的首地址,右参数是源字符串的首地址。源字符串必须以‘ \0 ’ 结束。strcpy会将源字符串的‘ \0 ’拷贝到目标空间中。目标空间足够大,以确保能存放源字符串。目标空间必须可变。如果目标空间不够大,那么就会造成非法写入,然后报错。

2024-04-27 18:51:12 865 1

原创 字符分类函数与字符转换函数

C语言中有一系列的函数是专门做字符分类的,也就是一个字符是属于什么类型的字符的。这些函数的使用都需要包含一个头文件是。上面的代码,我们将小写转大写,是-32完成的效果,有了转换函数,就可以直接使用tolower函数。通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0。代码演示:字符串中的小写字母转大写,其他字符不变。是能够判断参数部分的c是否是小写字母的。具体用法在Cplusplus中有介绍。使用库函数转换就是这样的。

2024-04-25 16:52:09 281

原创 C语言生成随机数

如果再深入了解⼀下,我们就不难发现,其实rand函数⽣成的随机数是伪随机的,伪随机数不是真正的随机数,是通过某种算法生成的随机数。真正的随机数的是无法预测下一个值是多少的。程序中在调用rand函数之前先调用srand函数,通过srand函数的参数seed来设置rand函数生成随机数的时候的种子,只要种子在变化,每次生成的随机数序列也就变化起来了。rand函数会返回⼀个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的大小是依赖编译器上实现的,但是大部分编译器上是32767。

2024-04-20 19:07:16 419

原创 C语言整型提升

C语言中整型算数运算总是以整型类型的精度来进行的。表达式中的字符和短整型操作数在使用之前被 转化为普通整型,这种转换称为整型提升。

2024-04-20 11:25:28 945

原创 二叉树与递归

下面是三种遍历的代码和计算树的大小,计算叶子的个数,树的高度和计算k层结点的个数,都是递归思想。前序遍历:根结点 —> 左子树 —> 右子树。后序遍历:左子树 —> 右子树 —> 根结点。中序遍历:左子树—> 根结点 —> 右子树。

2024-03-27 18:02:44 183

原创 堆排序(附降序代码)

这样就是一个升序的数组了。之前想过可以建立小堆进行排序,也是首尾交换,但是放在数组里面就算是降序了,所以这种方式适合降序排列数组的时候使用。

2024-03-24 15:48:58 554

原创 堆TOP K问题

建立一个k个数的小根堆,因为是找最大的k个数,所以要建立小根堆,这样每次都是当前最大的k个数里面最小的在堆顶,当前的数和堆顶比较,如果比堆顶大,就和堆顶交换,然后向上调整,如此循环最后得到最大的k个数。如果想要找出一组数据中的最大的k个值,如果直接建堆时间复杂度时O(n*logn),当数据量大的时候,不仅时间复杂度高,而且空间复杂度也很高为O(n),加入数据是1亿个,就会占用大量的空间。不是建立大根堆,如果建立大根堆,那么堆顶如果是最大的,那么就会一直卡着,后面的数据无法进入到堆里面。

2024-03-24 14:50:13 342

原创 树,二叉树与堆

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既然保存值域,也要保存结点和结点之间的关系,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法等。(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。需要注意的是二叉树和堆都是对数据的描述和存储的方式,不同的情况选择不同的存储方式,堆就是其中一种。:一个节点含有的子树的根节点称为该节点的子节点。

2024-03-23 20:45:05 931 1

原创 队列的实现(C语言链表实现队列)

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。因为数组头出了以后要把所有数据都往前挪动一位。只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)出队列:进行删除操作的一端称为队头。入队列:进行插入操作的一端称为队尾。

2024-03-23 17:47:25 124

原创 栈的实现(C语言数组栈)

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端。称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出的原则。栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。栈的删除操作叫做出栈。

2024-03-23 17:33:22 325

原创 C++引用

引用被称为变量的别名,它不能脱离被引用对象独立存在,这是在高级语言层面的概念和理解,并未揭示引用的实现方式。常见错误说法是“引用“自身不是一个变量,甚至编译器可以不为引用分配空间。引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。实际上,引用本身是一个变量,只不过这个变量的定义和使用与普通变量有显著的不同。但是引用自身占用内存,引用也是一种变量。在C语言中我们要交换两个数是这样的。如果用引用作为参数的话就是这样的。

2024-03-21 17:16:21 217

原创 C++基本认识

实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。这样写是不对的,必须。

2024-03-20 18:51:38 403

原创 C++认识及域的概念

命名空间域不仅可以定义变量,还可以定义结构体,定义函数等对于结构体的定义就是命名空间的名字要写在中间int x = 10;int val;int main()错误的。

2024-03-20 14:04:55 402

原创 Linux进程初步理解

进程信息被放在一个叫做进程控制块的一个数据结构(struct PCB)中,可以理解为进程属性的集合,其中包括了内存指针,指向程序所在的内存地址。无参数,返回值为pid_t,子进程的返回值是0,父进程的返回值为其子进程的pid,返回值为负数则创建失败。,该文件夹包含了所有的进程信息,每形成一个进程该目录下就会形成以该进程pid命名的文件夹。每个进程都有唯一的进程标识符,叫做PID,PID是结构体中的一个无符号整型。课本上讲的是,进程是程序的一个执行实例,正在执行的程序。:获得当前进程的父进程pid。

2024-03-11 18:06:08 270

原创 Linux中make和makefile

make是Linux中一个命令,与之匹配的是makefile,makefile是一个文件。make会根据makefile中的内容完成对应的工作创建一个名为makefile的文件vim打开makefile第一行是依赖关系,my.exe 是我们要生成的文件,后面是依赖文件列表,依赖文件列表可以有很多个第二行是依赖方法,就是我们要通过什么方式获得我们要生成的方式,依赖方法开头必须是Tab键,不能是空格(依赖方法可以不止一个,依赖关系下的所有命令都会执行,可以通过这样一次进行多步操作。

2024-02-02 21:29:33 278

原创 Linux动态库与静态库

可重定位目标文件以一种特定的方式打包成一个单独的文件,并且在链接生成可执行文件时,从这个单独的文件中“拷贝”它自己需要的内容到最终的可执行文件中。这个单独的文件,称为静态库。我们生成可执行程序时,直接把静态库打包到我们可执行程序里面,这样就会使我们的可执行程序变大,因为所有的库函数都放到了可执行程序里面。动态库和静态库类似,但是它并不在链接时将需要的二进制代码都“拷贝”到可执行文件中,而是仅仅“拷贝”一些重定位和符号表信息,这些信息可以在程序运行时完成真正的链接过程。

2024-02-01 23:53:58 894

原创 Linux下gcc的使用与程序的翻译

gcc是一款编译C语言编译器,可以把我们用vim写的代码编译成可执行程序。编译C++用g++进行编译,C++的文件后缀是test.cc或test.cpp或test.cxx如果要安装g++就执行以下命令sudo yum install gcc-c++//g++内核底层是gccgcc + 程序 就会形成可执行文件,默认是a.out,如果目录下已经存在,那么就会把a.out覆盖掉。gcc -o + newname + 程序:给编译后的可执行程序重命名。

2024-02-01 23:53:46 570

原创 解决Linux无法执行sudo命令

在我们的根目录下 /etc/sudoers 这个文件里面存在白名单,不是任何用户都能进行指令提权的,只有白名单里的人才能进行指令提权,也就是只有把用户加进这个文件夹里用户采用权限进行。就算我们改完,wq准备退出,会有报警,因为这是一件十分重要的失去,我们要十分确定,所有要在底行模式下输入**wq!sudo 是一种权限管理机制,管理员可以授权于一些普通用户去执行一些 root 执行的操作,而不需要知道 root 的密码。第二步,在100行左右,复制root那一行,然后把root改为我们自己的用户名。

2024-01-31 20:46:44 567

原创 Linux中vim编辑器的使用

vim是一款多模式的编辑器所谓多模式就是有几种模式供我们选择使用创建一个文件叫test.c,用vim打开就是这样就可以打开test.c进行编程刚打开时是无法进行输入的,默认进入的是命令模式命令模式:在命令模式下按“ i ”进入插入模式“ i ”是insert的首字母。在命令模式下按“ shift +;”表示冒号进入底行模式a:光标向后移一次进入插入模式o:新起一行进入插入模式插入模式:插入模式就是写代码的模式,这个模式下可以写代码,在插入模式下按Esc退出插入模式进入到命令模式。

2024-01-31 20:46:25 1219

原创 Linux软件包管理器yum

yum是Linux中软件下载安装的一个客户端,就像小米应用商店。

2024-01-30 23:40:29 953

原创 Linux权限

图中文件的权限,能读为1,不能为0,可以以二进制的形式描述权限,图中权限拥有者的权限就是110,所属组的权限时110,other的权限时001。现在使用root用户在ppp的文件夹下创建了拥有者和所属组都是root的文件,但是可以发现我们普通用户可以删除root的文件,这就是因为,我们删除文件实在ppp目录下进行的操作,我们具有写权限,所有可以删除。Linux中的root,我们刚买到云服务器,第一次登陆上,默认的就是root,root是我们Linux中的超级管理员,最大的特点就是不受权限约束。

2024-01-30 18:47:37 1238

原创 Linux指令执行的过程

我们每次输入命令前都会有一串字符串,这个叫命令行提示符,我们后面输入的命令会交给shell程序处理,处理的结构交给操作系统,操作系统返回的结果交给shell程序,shell程序处理后显示给用户。,我们操作windows 不是直接操作windows内核,而是通过图形接口,点击,从而完成我们的操作(比如进入D盘的操作,我们通常是双击D盘盘符)。但是我们执行命令行的时候并不是bash进行执行的,而是bash创建子进程执行,子进程帮用户进行命令行解释,bash等待子进程执行的结果。用户与内核的关系大概是下面这样。

2024-01-29 19:04:47 247

原创 Linux(CentOS)几个常用快捷键

输入ctrl + r 会出现另一个命令框,输入要查找历史命令的关键字,如果有多个历史命命令都有此关键字,出现最近的一次,然后再次按ctrl + r可以往上查找其他对应的命令,按回车执行该命令,按左右键选中该命令。如果当前输入的命令片段有且只有一个与之匹配,那么按一下Tab键就可以自动补全命令,如果有多个要按两次会弹出所有可能与之对应的命令。如果出现程序执行的时候一直刷屏,比如查看大文本,可以按ctrl+c结束进程,按一次没用就多按几次。功能:可以按顺序翻找历史命令。命令:ctrl + r。

2024-01-29 10:02:39 281

原创 Linux(CentOS7)与用户电脑传输文件(sz与rz)云与云(scp)

rz和sz是Linux/Unix同Windows进行Zmodem文件传输的命令工具。输入rz按回车,就会弹出Windows的文件窗口,选择文件就可以接收。之前学习的文件压缩命令就可以用来压缩文件然后Linux进行收发。r为receive接收,都是相对与Linux来看的接收和发送。rz和sz中的z为Zmodem文件传输协议的首字母。sz + 文件直接按回车就可以选择发送的路径。把文件发送到Windows。

2024-01-28 21:58:43 318

原创 Linux(CentOS7)打包和压缩(zip与tar命令)

我们对这样打包的文件进行解压,然后发现目录下所有的文件都在,说明这样打包是对的,为什么要这样呢,因为文件时树状结构的,我有要“ -r ”进行递归式的压缩,把所有的文件都压缩进来。但是我们会发现,单纯zip压缩的话,我们会发现只打包了一个文件夹,但是里面是空的,什么都没有,这说明我们打包的方式是错误的。同样可以解压到指定的目录,不过不同于zip,tar的命令为 -C且C为大写。所以,正确的打包方式为zip -r + 压缩后的文件名 + 要压缩的目录。压缩命令:zip + 压缩后的文件名 + 要压缩的目录。

2024-01-28 21:38:41 1072

原创 Linux(CentOS7)常见指令的常见用法(下)

more + 文件,我们cat查看大文件,比如10000行,就会出现刷屏的情况,这是就可以使用more命令查看文件,more + 文件就可以把文件占满一屏,可以按回车逐行下翻,不看就可以按q退出。输入重定向,我们输入默认从键盘输入,从键盘文件读取内容输出到显示器文件,但是输入重定向以后就是从文件中读取,可以发现我们直接cat就能得到文件内容,这样使用就可以,但是和输入重定向的原理是不同的。年是大写的Y,月和日都是小写的英文首字母,时分秒是大写的英文首字母,可以直接输入大写的X也是时分秒的输出。

2024-01-28 20:15:58 589

原创 Linux(CentOS7)常见指令的常见用法(上)

rm + 文件为删除文件,然系统问是否要删除,输入y是确认删除,输入n是不删除,但是rm只能删除文件,不能删除文件夹,所有要用rm -r(r是recursive的首字母,递归的意思)进行递归删除,但是每次都会询问文件要不要删,每次都要输入y,所有可以使用rm -rf进行递归强制删除,这样就不会进行询问了。nano后面跟文件,可以编辑文本,进入编辑就是这样,然后按ctrl + x推出,然后会提示,然后按y保存,然后提示命名,可以重新命名,那么就会产生一个新文件,原来的文件的文本内容不变。

2024-01-27 23:01:03 898

原创 51串口中断不会重复进中断(记录一次51串口中断的思考)

打开中断在发送数据的时候就会进入中断。事实是:进不进中断只和RI或者TI是否等于1有关其中一位为1就会进入中断,这也就解释了为什么之前没有多次进入中断了,因为同级中断不会打断,在执行完此次中断TI就已经被置为0。发送多次只进了两次中断,是因为中断前面执行的很快,我们只是在RI=0后把RI置为了1,我们按多少次,RI就还是1,在下一次中断RI被置为0,出来第二次中断自然就不会再次进入。于是就得出结论,原来我理解的是错的,原来以为,发一次或者接收一次数据就会进一次中断,进中断的次数和收发次数相等,其实不然。

2023-11-17 18:07:42 450

原创 如何判断环形链表入环节点(交点)(附代码)

1.因为fast是slow的二倍,在slow入环后开始算,fast先前数与slow的距离最大肯定小于C,假设slow走了一圈,那么fast就走了两圈,fast已经比slow多走了一圈,所以在这两圈内肯定已经相遇过,所以相遇点X不会大于C。2.L越大圈越小,n就越大,L越小圈越大n就越小,所以n可以无穷大,但是最小呢,假设n为0,fast还没有走完一圈就相遇了,这说明slow在fast前面,显然不成立。slow刚入环,fast在solw前方x处,假设环的周长是C,那么在slow走C减x次后二者相遇。

2023-11-15 16:47:34 121 2

原创 为什么结构体里面可以定义结构体指针(链表)

对那个结构体指针来看,就是创建这样一个结构体就要创建一个指向这种结构体的指针。声明更像是在说,如果要创建结构体,就要创建那么多变量,例如上面的创建的struct S,就是在说,如果要创建struct S类型的变量,那么就要创建两个整形,一个struct S类型的指针,一个struct L类型的指针,如果没有这个结构体,我们一样 可以创建这样两个指针。整个结构体里面的成员和结构体并不冲突,是成员一起构成了结构体,只不过里面多了一个结构体指针类型的成员,他并不指向此结构体,因为只是声明了此结构体,并不占内存。

2023-11-05 14:42:12 523 5

原创 关于函数传参类型问题的思考与自我解答

3.C语言目前的规则就是这样,传参只是传一个地址,并没有传地址所存变量的类型,对地址如何操作由程序员决定。2.C语言,毕竟C生万物,C语言更讲求速度,目前的设计,代码执行更快,让程序员自己写要怎么操作,让编译器省去判断的步骤,代码执行更快,虽然程序员要自己多写几句。1.如果那样设计的话,在每次执行自己定义的时候,底层或者汇编上面都会有一个识别的过程,会降低代码执行的速度,而且当函数不仅仅是那些简单的指针,例如出现结构体或着一些更复杂的,汇编上可以只有几句话,但是编译器要进行很大的修改。

2023-10-03 18:02:19 47

原创 创建一个返回值为函数指针的函数

函数指针:指针存的是函数的地址Add或者&Add都是函数的地址,在调试中虽然两者的类型有差异,但是使用起来都一样上面代码定义函数指针变量,int为Add的返回值,(int, int)为Add的参数类型int main()return 0;上述代码中和 **int r = Add(3, 5);**效果一样,可以直接通过传地址进行函数调用。

2023-09-30 21:43:29 139 1

原创 二维数组传参的本质(指针数组和数组指针)

parr[0]等同于对parr首元素解引用, [ ] 的作用就相当于解引用(*)符号。

2023-09-30 17:05:40 45

原创 冒泡算法(数组从低到高排序)

一旦前面的数比后面的大,那么前面的数就会被提到后面,所一轮中肯定存在一个最大的数,最大的数就会一直和后面较小的比较,所以就会被提到最后面。如果进入 if 说明没有排好顺序,就被置 0 ,下一次循环前再次置 1 ,如果没有进入 if 说明全部排好,flag不,如果不改变就知道排好,判断flag退出循环,提高执行效率。这样的数组时,只需要一次就能排好顺序,后面的就不需要再次循环,于是加上了flag位。当出现已经排序好的数组时,例如,9,1,2,3,4,5,6,7,8。

2023-09-23 14:26:16 146 2

原创 数二进制中1的个数

数二进制中1的个数

2023-09-17 12:06:47 31 1

原创 不通过第三个变量交换两数的方法

不通过第三个变量交换两数的方法

2023-09-17 08:58:10 171 1

原创 关于数组越界导致死循环

在**32位**环境下会导致死循环,不停地输出“Hello”。

2023-09-09 16:00:57 45 1

原创 static与extern

变量a,i,j在add的源文件中声明,在main这个源文件这里可以使用,但其他没有用extern声明的源文件中不能使用,但也可以在头文件中用extern声明,这样包含这个头文件的源文件都可以使用这些变量。全局变量具有外部链接属性,static修饰全局变量以后,外部链接属性就变为内部链接属性,其他的c文件也无法使用此变量。但是b因为被static修饰,他的生命周期是整个程序,但是作用域不变,仍然是第三个大括号内部。,但是只有包含用extern声明的文件才可以使用此变量,其他如果没有声明则不能被使用。

2023-09-07 16:01:36 79

空空如也

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

TA关注的人

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