一、
memcpy函数是我们经常会用到的一个函数,它和strcpy函数十分类似,但是
strcpy函数只能处理字符串,而memcpy不指定类型,不管什么类型都可以处理。
memcpy函数的声明如下:
memcpy函数从存储区 str2 复制 n 个字节的数据到存储区 str1。注意n的单位是字节。
memcpy函数实例演示如下:
自定义函数的代码如下:
我认为想要能够处理各种数据,就肯定不能直接地拷贝,应该从内存入手,我们可以一个字节一个字节地将src指向的数据拷贝给dest指向的空间,这也是为什么我们n的单位是字节。
char*类型的指针每走一步的长度是1个字节,我们可以把传进去的dest和src强制转换为char*类型指针。
这样我么不管传入什么类型的指针,都先用void类型接收,在拷贝时再转换为char类型。
自定义函数my_memcpy实例演示如下:
二、
我们现在想要尝试看看my_memcpy函数能不能实现把数据自身的一部分拷贝给自身,例如下面:
能否将2,3,4,5拷贝放在4,5,6,7的位置上。拷贝完后这个数组预期排列是:
1,2,3,2,3,4,5,8,9,10。
下面是演示:
我们发现结果并不对,我们用图片来演示以下这个过程:
这是最开始。
第一步。把arr1[1]拷贝给arr1[3]。
第二步,把arr1[2]拷贝给arr1[4]。
第三步,把arr1[3]拷贝给arr1[5]。
此时我们发现,arr1[3]由于之前的拷贝已经变为了2,所以此时拷贝给arr1[5]的也是2。
第四步,把arr1[4]拷贝给arr[6]。
拷贝结束,此时数组arr1[]={1,2,3,2,3,2,3,8,9,10}。
我们发现,当内存出现重叠的情况下,使用memcpy函数拷贝可能无法达到我们想要的效果。
接下来介绍的memmove函数就可以用来解决这个问题。
三、
memmove函数的声明如下:
memmove函数能够从str2复制n个字节的数据给str1。这一点和memcpy函数
是一致的。但是在str1与str2,出现重叠时,memmove函数更加安全。
memmove函数能够保证str2的数据在被覆盖前复制给str1。
其实memmove函数就是memcpy函数的升级版,它包含了memcpy函数的功能,并且在str1与str2出现重叠时也能实现正常拷贝。
我们再次用memmove函数来拷贝上面提到的数组arr1。
运行结果如下:
我们如愿以偿地让把原本arr1[1],arr1[2],arr1[3],arr1[4]拷贝给了arr1[3],
arr1[4],arr1[5],arr1[6]。
我们想要自定义实现memmove函数,其实就是在我们原本的自定义函数my_memcpy函数的基础上解决掉重叠问题就行了。
我们再来看这个数组,如果想要保证arr1[3]和arr[4]不被覆盖掉,我们可以尝试从后往前拷贝,也就是先把arr[4]拷贝给arr[6],然后把arr[3]拷贝给arr[5],然后把arr[2]拷贝给arr[4],最后把arr[1]拷贝给arr[3]。
从后往前拷贝图示如下:
我们得让dest和src都先指向最后,再向前拷贝。
拷贝结束。
按照上面的想法写出下面的代码:
运行结果如下:
但是这段代码是有缺陷的,当我们以下图所示的形式拷贝时,就会发生错误。
我们希望拷贝完后的排列是1,2,3,6,7,8,9,8,9,10。
使用my_memmove函数拷贝运行结果如下:
并不符合我们的预期,我们发现my_memmove可以实现dest>src的情况,当时无法实现dest<src情况。而想要解决这个问题,只需要从前往后拷贝就好了。
从前往后拷贝图书如下:
所以我们得分情况,当dest>src时,我们从后往前拷贝,当dest<src时,我们从前往后拷贝,至于dest==src时,两种拷贝方法都行。
最后我们自定义的my_memmove函数代码如下:
实例运行结果如下:
dest<src时:
dest>src时:
dest==src时: