当前位置: 首页 > news >正文

C语言中的内存函数

字符函数和字符串函数的章节结束了,接下来我们进入到C语言中的内存函数

今天的主角有:memcpy 函数、memmove 函数、memset 函数、memcmp 函数

一 . memcpy 函数

(1)memcpy 函数的使用 

这个 memcpy 函数是专用于内存拷贝的,大家是不是觉得很熟悉,我们才刚刚学习过用于拷贝的函数 —— strcpy 函数和 strncpy 函数,那么它们之间有着怎样的区别呢?

我们之前学习的 strcpy 函数、strncpy 函数是专用于字符串之间拷贝字符的,那么今天我们将要学习的 memcpy 函数诸君看到标题也能知道这个是用于内存拷贝的,它是不仅仅局限于拷贝字符串的,而是所有类型都能拷贝,并且,它可没有什么 memncpy,它本身就能对我们拷贝的元素个数进行限制

(1 . 1)对字符串的拷贝:

(1 . 2)对整型的拷贝:

如上图所示,我们的 memcpy 函数的运用还是相当简单的,有着前两期对这一系列函数的讲解,我相信聪明的诸君理解起来都是非常之简单的,轻松拿捏。如果是没有看过前两期的小伙伴,我建议还是可以去看一看的,能够帮助理解

(2)memcpy 函数的模拟实现

咱们这里直接以整型为例:

(2 . 1)使用 if 循环:

看过前两期的朋友我无需多言,在我们的 My_memcpy 内就是进行的一个简单的赋值、前进再循环

大家可以注意到,我们原 memcpy 函数的格式:

它的接收参数和返回值都是 void * 类型的,我们虽然是用整型举例,但我们实质还是模拟实现 memcpy 函数,我们不能只用整型,也得遵循 void * 类型的接收返回,我们这里虽然是整型类型,但是朋友们请注意了,我们在赋值时用的是 char * 的强转,为什么不用 int * 强转呢?这是因为我们这里需要拷贝给的正好是 20 个字节长度,但如果我给你 17 个字节呢?4 次拷贝结束,剩下的 1 个字节如何处理呢?所以我们选用 char * 类型一个字节一个字节的拷贝是一种更加严谨的操作

我们这个:dest = (char*)dest + 1 为什么不写成:(char*)dest ++ 呢?直接一步到位,这一次我们为什么要用这样 “ 原始 ” 的方式呢?因为我们的强转是一种临时操作,在我们强转之后在解引用的时候,dest 已经不是(char*)的类型了,它依旧是(void*)类型。这个时候有同学要问了,那这样呢:++(char*)dest,这种前置 ++ 是会优先运算的,这个 ++ 的时候我们 dest 还是(char*)的类型,但是这样的方式看似可行,是强转后的马上++,但是这样的方法不能保证在所有的编译器上正确运行的。所以我们只能返璞归真,用这种形式

(2 . 2)使用 while 循环:

while 循环我们直接用 num -- 作为循环条件,直至 num 为 0 自动跳出循环,这一点相信诸君不难理解吧 

一 . 一 . memcpy 函数不能用于重叠的内存拷贝

什么叫重叠的内存拷贝呢?如下:

具体解析咱们文字不好说,我用画图的方式给大家呈现:

诸君可以看到,当我们拷贝对象和地址有部分重叠时,当我们需要把 “ 3 ” 拷贝到 “ 5 ” 这个位置的是偶,我们的 “ 3 ” 已经不是 3 了,这个时候它已经被 1 替换掉了

有的同学坚信实践是检验真理的唯一标准昂,自己去试了一下发现没有问题啊,怎么这样说呢,那是因为我们特殊的编译环境,VS上的库函数 memcpy 也能实现重叠内存的拷贝,但并不是所有编译器上都能实现,可能在其他编译器就跑不动了呢?在我们C语言的标准规定中是定义memcpy 函数不负责重叠内存的拷贝,非要使用的话,结果是未定义的,所以我们尽量避免用memcpy 函数去进行重叠内存的拷贝,咱们术业有专攻,进行重叠内存拷贝的角色另有人选,那就是我们接下来即将登场的 memmove 函数!

二 . memmove 函数

(1)memmove 函数的使用  

memmove 函数的使用格式跟我们之前讲的一系列函数大差不差,没啥新知识点,咱们多的不说少的不唠,直接演示:

大家看,这一个 memmove 函数就能完美执行我们重叠内存的拷贝,这个没有什么好说的点,咱们直接进入下一环节了昂

(1)memmove 函数的模拟实现  

解析:memmove 函数的模拟实现有很重要的点,因为我们并不了解 memmove 函数实现的底层逻辑,我们不可能直接一步到位去实现对重叠内存的拷贝,但是我们可以多思考一下,采用逆向思维:当我们需要拷贝的地址在拷贝对象之后我们的内存会被拷贝时覆盖,那我们不妨试试从后往前拷贝,这样子就能巧妙地避开我们被拷贝覆盖的内存

文字不太好理解,我来在图上为诸君解析:

如图所示,我们可以看到我所列举的两种情况:

(1 . 1)情景一:dest 在 sour 之后

这个时候我们从前往后进行拷贝,就会遇到我们使用 memcpy 函数进行重叠内存拷贝时的问题,我再把那张图拿下来大家看一下:

 此时我们如果还是执迷不悟依旧要使用从前往后的常规拷贝方式,那么我们的内容一定会被覆盖掉,所以我们应当选择逆向思维从后往前拷贝,大家可以发现此时从后往前就可以很巧妙的避开拷贝时的重叠元素:5 -> 7,4 -> 6,3 -> 5,2 -> 4,1 -> 3

(1 . 2)情景二:dest 在 sour 之前

当我们的拷贝地址在拷贝对象之前的这种情景,我们会发现此时的从后往前拷贝会使我们的重叠内容被覆盖,所以我们在 dest 在 sour 之前的这种情况还是选择从前往后拷贝,这样子我们的内容就不会被覆盖了

三 . memset 函数

memset 函数的使用

如图,我们的 memset 函数是专用于修改字符串中单个字符的函数

memset 函数中有着三个参数,分别是什么含义呢?

void * ptr:我们要修改的字符串中字符的起始地址

int value:修改的目标字符(将原字符改成什么字符,注意:只能修改成单一字符) 

size_t:修改字符的个数(注意:只能连续修改字符

使用格式非常简单,如下图:

四 . memcmp 函数

memcmp 函数的使用

大家是不是觉得有点眼熟哇,之前我们学到过 strcmp 函数和 strncmp 函数,这俩是专用于字符串大小的比较,比较的是对应字符的ASCLL码值的大小是吧,这个 memcmp 函数是用于比较内存中字节块的大小,不仅仅局限于字符串,并且呢它没有 memncmp 的形式,也是自带对比个数限制的

返回值:这个返回值跟我们的 strcmp 函数和 strncmp 函数的C语言规定是一模一样的:

ptr1 > ptr2 返回大于 0 的数;ptr1 < ptr2 返回小于 0 的数;相等则返回 0

(同样,在我们的 VS 中相对应的也只会返回 1、- 1、0,其他编译器可能会有所不对)

(1)整型间的比较:

(2)字符间的比较:

这个 memcmp 函数还是相当简单的,没啥难点,都是我们学过的老朋友了昂,我觉得也不用给诸君过多赘述了,就这样吧,如果有小伙伴有所疑问的话,欢迎在评论区和私信跟我讨论哦

OKK,有关C语言中的内存函数的章节我们就到此为止啦。诸君动动发财的小手,如果此篇文章对你有所帮助的话,不妨点点赞点点关注噢!就这样吧,咱们下期再见!与诸君共勉!!!


http://www.mrgr.cn/news/55526.html

相关文章:

  • Spring AI 整体介绍_关键组件快速入门_prompt_embedding等
  • C#删除dataGridView 选中行
  • 枚举的使用举例说明
  • C++智能指针及其应用
  • Nature 正刊丨空间蛋白质组学确定JAKi是一种致命皮肤病的治疗方法
  • 2024系统分析师考试---论区块链技术及其应用
  • 没有网络限制!超简单本地部署 Llama3 的方法
  • MySQL-30.索引-介绍
  • Rat工具:vshell 4.9.3简单使用介绍
  • C++实现循环队列和链式队列操作(实验5--作业)
  • J1:ResNet-50算法实战与解析(鸟类识别)
  • webpack 老项目升级记录:node-sass 规定的 node v8 提升至支持 node v22
  • Selenium自动化测试全攻略:从入门到精通
  • Anchor DETR论文笔记
  • Telink 2.4G proprietary protocol 泰凌2.4G私有协议
  • Windows下安装并使用 NVM(Node Version Manager)
  • 材料研究与应用
  • 高级sql技巧
  • git配置以及如何删除git
  • Python包---numpy1
  • unix系统的终端、进程、进程组、会话、控制终端、作业控制之间的关系
  • Python内置函数classmethod()详解
  • 有没有好用的待办事项清单软件? —— 一文带你了解
  • 企业成本与时间管理新策略 低代码自动化显身手
  • 《深度学习》模型的部署、web框架 服务端及客户端案例
  • 提升小学语文教学效果的思维导图方法