1. memcpy使⽤和模拟实现
2. memmove使⽤和模拟实现
3. memset函数的使⽤
4. memcmp函数的使⽤
一.memcpy的使用与模拟实现
1.定义:
注意:1.memcpy返回的是目的地的指针
2.使用时要包含头文件string.h
3.num指的是拷贝的个数(单位为字节)
2.使用:
3.模拟实现:
ps:这里有一个值得注意的电就是dest=(char*)dest+1可不可以写成dest=(char*)dest++,答案是不合理的,主要是因为后置++的优先级高,所以是先dest++,但dest是一个void*类型,不是完整的指针类型,没有办法给他移动字节
思路整理: 通过对memcpy的学习,我们知道了这是一个用来拷贝数据的函数,并且它本身并不care它要拷贝的数据是什么类型的,所以这里我们传参的时候就要写成void* 的指针,和原函数保持一致,由于我们要用这个函数来实现所有类型数据的拷贝,所以用char*类型的指针来逐个字节进行交换最合适不过了,但void* 的指针不能直接进行解引用,要进行强转,然后在逐个字节进行交换时,两个指针要往后走,至于走到哪,这里就拿while循环来判断,将num作为循环判断条件,当num为0时交换完成,循环正好停止,但是因为强转类型是是临时的,所以这里直接让指针++就不行,还要再次进行强转才可以,这里是比较容易忽视的一个点。并且这个函数还要返回目的地的地址,并且是void*类型的,但是直接在结尾返回dest是有问题的,因为在进行了一系列循环后,指针早就跑远了,这时候我们就可以在开头就先把这个地址传给另一个指针ret,最后在结尾返回指针ret就可以了,这时候这个函数就比较完善了,但因为这里用到了指针,所以在使用之前其实可以先判断一下是否为空指针,这时候就用到了assert,加上这个的话函数就更加健壮了。
4.局限性:
一般来说,memcpy是不支持拷贝重叠数据的,但在某些系统上却也是可以实现的,但很明显,我上面自己写的这个memcpy如果重叠拷贝的话是会出错的:
我们通过逐个字节来交换来进行拷贝,但比如这里的源头在该取3来进行交换时,这时候其实3已经被1给覆盖了,也就是说这时候你取出的不是3,而是1,所以这时候就出错了啊。
二. memmove使⽤和模拟实现
1.定义:
• 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
• 如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理。
2.使用:
3.模拟实现:
思路整理: 通过对memmove函数的学习,我们发现这个函数是既可以实现重叠内存的拷贝,也可以实现不相关内存的拷贝,这时候我们在实现这个函数的时候就需要分情况来思考了,我们通过下面这个图来理解:
情况一的时候如果还是先从源头开始拷贝的话就会出现一种现象:在拷贝3的时候,这个3已经被1给覆盖住了,你拿到的不是3而是1,这就出错了啊,所以这个时候我们就需要从末尾开始拷贝,从源头的末尾开始拷贝,依次放到目的地的末尾,这样就可以正确拷贝了
情况二的话是目的地在在源头左边,这个时候就可以从源头开头依次进行拷贝,也就是和上面的my_memcpy道理一样
情况三不属于重叠内存的拷贝,无论是从左还是从右拷贝都可以
既然这样话,我们可以以dest和src的位置来划定情况,当dest在src左边时从左开始拷贝,其他两种情况从右开始拷贝。
这里其实还需要进行解释的一点是在从右开始拷贝的时候怎么找到src和dest的末尾,这里我们通过(char*)dest + num (char*)src + num 分别找到了dest和src的末尾,接着我们通过while循环,并且以num-- 作为循环判断条件,这时候随着num的变化,指向dest和src的指针也跟着移动,从右向左进行交换,当num为0时,交换完成,循环停止。
综上:memmove函数的作用应该是远大于memcpy函数的,但要是更加细分的话,memmove的运行效率在仅仅拷贝不重叠的字符串时是要低于memcpy的,但memmove函数的作用范围明显是比memcpy大的
三. memset函数的使用
1.定义:
简而言之:memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。
ptr:指向要填充的内存块的指针。
value:要设置的值(以整数形式传递,但实际会被转换成 unsigned char 类型)。
num:要设置的字节数。
2.使用:
memset 用于将一块内存区域中的每个字节都设置为某个给定的值,通常用于初始化数组或者结构体,或者清除内存中的数据
初始化结构体: