C语言——内存操作函数(memcpy、memmove、memcmp、memset)


📘前言

本文章会详解C语言进阶内容,有关内存操作函数(memcpy,memmove,memcmp,memset)的使用说明、API文档该类函数原型以及模拟实现内存函数


📗 一、memcpy(内存拷贝)

📖 1. 函数说明

首先我们从API文档中搜索memcpy查看一下该函数的原型
函数原型

可以看出该函数有三个参数,那么这三个参数的作用分别是什么呢?

该函数的实现思路是将把源头数据const void * source拷贝到目标数据void * destination里去,最后一个参数size_t num则代表需要拷贝多少个字节,这个函数在遇到'\0'的时候并不会停下来。如果source和destination有任何的重叠,复制的结果都是未定义的。

那么它与字符串函数strcpy有什么区别呢?

我们可以看出memcpy的函数参数的返回类型是void*,所以memcpy不考虑你拷贝的数据是何种类型,都可以将原指针指向的空间传入num个字节数拷贝到dest指针处;而strcpy的参数是已经被写死了,传入的类型必须是char类型数据,实现较为单一。

简单的实现一下该函数
在这里插入图片描述
我们定义了两个int类型的数组,接着使用memcpy,如果想拷贝五个元素到arr2数组中去,因为int类型数组一个元素大小占4个字节,要拷贝五个元素,则第三个参数给的是20个字节。


📖 2. 模拟实现

因为是模拟实现,所以我们需要设计的函数返回类型,参数个数,参数类型都要与其一致。
在这里插入图片描述

由于数组元素要考虑字节数,所以就涉及到大小端的问题,这里我们以小端为例:1 在内存中十六进制是 0x 00 00 00 01,小端存储是低位放在低地址,高位放在高地址。
在这里插入图片描述

如果我们需要向上面图解所示,将arr1数组的元素按照每一个字节拿到arr2数组中,一共拿20个字节,我们怎么才能做到一个一个字节拿出来呢?

首先我们需要对指针解引用操作,把*src的内容放到*dest中去,因为一次要拷贝一个字节,我们可以直接强制类型转化成char*类型就可以访问一个字节了。接着继续往后访问,还需要强制类型转化成char*类型再+1让指针往后走;该操作需要执行的次数取决于参数num的取值所以这里用while循环,随着每一次的操作,num–,直到num为0循环结束。最后该函数设计的时候返回的是一个void*指针,所以我们可以在循环操作前,先定义一个void* res用来存放最初始的dest程序结束,return res;就可以了。


💡 3. 运行图示:

在这里插入图片描述


📗二、memmove

📖 1. 函数说明

由上述memcpy函数想到一个问题,我们在拷贝的时候能不能从同一个数组里,将arr1数组前五个元素拷贝到,从3开始3,4,5,6,7这个位置上,理想结果arr1数组应该是{1,2,1,2,3,4,5,8,9,10}这样的结果可事实真是如此吗?接着我们调试,从监视里观察arr数组的元素
在这里插入图片描述

从图中可以看出arr1数组运行完的结果与预期的有所差异,下标为2到下标为6的元素变成了1,2,1,2,1了!
在这里插入图片描述
由图所示从同一个数组中不同位置进行拷贝操作的时候,原空间和目标空间有重叠的时候,拷贝过程中已经将目标空间的数据已经覆盖掉了,后续再进行拷贝操作的时候,拷贝的数据已经不是原空间的数据了。
在这里插入图片描述
如果是如上情况(src在dest的右边并有重叠部分)就得从4开始拷贝,从前向后拷贝。反之如果src在dest的左边,则需要从后向前拷贝,如果没有重叠部分,从前向后or从后向前都是可行的,因为没有数据不会在拷贝前被覆盖了

所以我们不能使用memcpy函数进行在同一个数组里进行内存拷贝!这时候就要用到另一个内存函数memmove


📖 2. 模拟实现

此时我们只需思考从后往前拷贝时,应该如何实现
在这里插入图片描述
从图中可知,src是<dest的,所以需要从后往前拷贝,要先找到8这个数,就是src最末位字节,这里是第20个字节,则需要找个下标为19的那个字节,所以用起始位置加上num偏移量-1,则找到了元素为8的字节空间,紧接着解引用赋值给dest末尾的字节空间
在这里插入图片描述

从调试窗口中可以看出,结果与开始的预测相同
在这里插入图片描述
模拟完成

💡 3. 运行图示:

在这里插入图片描述


📗三、memcmp

📖 1. 函数说明

函数原型
在这里插入图片描述
memcmp是比较内存区域ptr1和ptr2的前num个字节,比较的是内存大小,*注如果两个字符串相同且num值大于字符串长度的话,不会在\0出停下程序,会继续往后进行比较,直到达到num次数

📖 2. 函数的功能(主要作用)

memcmpstrcmp函数功能相似,只不过是可以对所有类型都进行一个字节一个字节的比较,逐字节比较内存的大小。
返回值有三种情况

‘< 0’ :"参数ptr1"与"参数ptr2"逐字节比较,"参数ptr1"数据 < “参数ptr2”;(VS编译器下返回值为 -1
‘= 0’: "参数ptr1"与"参数ptr2"内存大小相等;(VS编译器下返回值为 0
‘> 0’:"参数ptr1"与"参数ptr2"逐字节比较,"参数ptr1"数据 > “参数ptr2”。(VS编译器下返回值为 1

举 ‘>0’ 一例说明:
在这里插入图片描述


📗三、memset

📖 1. 函数说明

函数原型
在这里插入图片描述
以字节为单位来设置值
参数分别为:
1 . 一个指向需要被修改的内存空间的地址
2 . 指定修改的内容(int类型)
3 . 需要修改的字节数

📖 2. 函数的功能(主要作用)

memset函数的作用:在指向的内存空间的前num个字节内容修改成所指定的int value的内容,有些类似于memcpy的工作原理。
图示说明
在这里插入图片描述


📝 总结

以上就是有关C语言进阶的内容,内存操作函数部分的模拟实现和函数使用说明及方法。
希望该篇文章对大家的学习有所帮助,期待与大家共同进步,持续更新中…
点个关注点个赞👍吧!
💗🤍💕💖

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_NunU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值