内存函数
1. memcpy函数
(1)介绍
这里通过memcpy
的定义我们可以看这个函数包含三个参数,destination
就是拷贝的目的地,source
就是拷贝的源头,num
就是拷贝的个数。
(2)使用
- 这里要包含头文件
string.h
- 这里的个数最好写成sizeof(类型)* 个数的形式,因为你拷贝什么类型未定
(3)memcpy 函数模拟实现
思路整理: 通过对memcpy
的学习,我们知道了这是一个用来拷贝数据的函数,并且它本身并不care它要拷贝的数据是什么类型的,所以这里我们传参的时候就要写成void*
的指针,和原函数保持一致,由于我们要用这个函数来实现所有类型数据的拷贝,所以用char*类型的指针来逐个字节进行交换最合适不过了,但void*
的指针不能直接进行解引用,要进行强转,然后在逐个字节进行交换时,两个指针要往后走,至于走到哪,这里就拿while循环来判断,将num
作为循环判断条件,当num为0时交换完成,循环正好停止,但是因为强转类型是是临时的,所以这里直接让指针++就不行,还要再次进行强转才可以,这里是比较容易忽视的一个点。并且这个函数还要返回目的地的地址,并且是void*
类型的,但是直接在结尾返回dest
是有问题的,因为在进行了一系列循环后,指针早就跑远了,这时候我们就可以在开头就先把这个地址传给另一个指针ret
,最后在结尾返回指针ret
就可以了,这时候这个函数就比较完善了,但因为这里用到了指针,所以在使用之前其实可以先判断一下是否为空指针,这时候就用到了assert
,加上这个的话函数就更加健壮了。
(4)局限性
其实C语言中规定memcpy
函数不用来拷贝重叠内存,但我们还是来测试一下
首先我们用自己模拟的my_memcpy
来测试一下
显然这里我们可以发现用我们自己模拟的my_memcpy
函数拷贝重叠内存时发生了错误,我们可以借助下图来进行理解
我们通过逐个字节来交换来进行拷贝,但比如这里的源头在该取3来进行交换时,这时候其实3已经被1给覆盖了,也就是说这时候你取出的不是3,而是1,所以这时候就出错了啊。
既然我们自己模拟的my_memcpy
不能完成这个任务,那么库函数中的memcpy应该也不行吧,下面我们来试一下
到这里有些同学可能就坐不住了,这memcpy
不是说不能拷贝重叠内存的吗?这里为什么还是可以啊,其实不然,这只是在部分编译器中可以实现,但你不能保证它在任何情况下都可以做得到的,并且我们有专门的函数来实现这个功能,所以不建议用memcpy
这样干。
2.memmove函数
(1) 介绍
这里通过memmove
的定义我们可以发现这个函数也是有三个参数,包括目的地、源头、拷贝个数
(2)使用
这里我们看到memmove
函数不仅可以实现重叠内存的拷贝,而且也可以实现不相关两组数据的拷贝。
(3)memmove函数模拟实现
思路整理: 通过对memmove函数的学习,我们发现这个函数是既可以实现重叠内存的拷贝,也可以实现不相关内存的拷贝,这时候我们在实现这个函数的时候就需要分情况来思考了,我们通过下面这个图来理解:
- 情况1的时候如果还是先从源头开始拷贝的话就会出现一种现象:在拷贝3的时候,这个3已经被1给覆盖住了,你拿到的不是3而是1,这就出错了啊,所以这个时候我们就需要从末尾开始拷贝,从源头的末尾开始拷贝,依次放到目的地的末尾,这样就可以正确拷贝了
- 情况2的话是目的地在在源头左边,这个时候就可以从源头开头依次进行拷贝,也就是和上面的
my_memcpy
道理一样。
3.情况三不属于重叠内存的拷贝,无论是从左还是从右拷贝都可以 - 既然这样话,我们可以以dest和src的位置来划定情况,当dest在src左边时从左开始拷贝,其他两种情况从右开始拷贝。
这里其实还需要进行解释的一点是在从右开始拷贝的时候怎么找到src和dest的末尾,这里我们通过(char*)dest + num
(char*)src + num
分别找到了dest
和src
的末尾,接着我们通过while
循环,并且以num-- 作为循环判断条件,这时候随着num的变化,指向dest
和src
的指针也跟着移动,从右向左进行交换,当num为0时,交换完成,循环停止。
(4)memcpy和对比memmove对比
综上所述:memmove
函数的作用>> memcpy
的作用,memcpy
能做的memmove
可以做,memcpy
做不了的memmove
也能做。
3. memset函数
(1)介绍:
通过memset的定义我们可以看到这个函数包含了三个参数
一般情况下这个函数可以用来内存的初始化、清空数组、给特殊值
(2)使用
这个函数比较简单就不再过多介绍。
4. memcmp函数
(1)介绍
(2)使用
注意这里比较的是内存中的大小。
5.总结
这期我们主要学习了memcpy
函数、memmove
函数及两个函数的模拟实现、memset
函数和memcmp
函数。这期中比较难一点理解的就是memmove
函数的模拟实现,大家可以反复翻看,加深理解,注意体会其中的思想。