一、

memcpy函数是我们经常会用到的一个函数,它和strcpy函数十分类似,但是

strcpy函数只能处理字符串,而memcpy不指定类型,不管什么类型都可以处理。

memcpy函数的声明如下:

memcpy函数与memmove函数的自定义实现_数据

memcpy函数从存储区 str2 复制 n 个字节的数据到存储区 str1。注意n的单位是字节。

memcpy函数实例演示如下:

memcpy函数与memmove函数的自定义实现_数组_02

自定义函数的代码如下:

memcpy函数与memmove函数的自定义实现_数据_03

我认为想要能够处理各种数据,就肯定不能直接地拷贝,应该从内存入手,我们可以一个字节一个字节地将src指向的数据拷贝给dest指向的空间,这也是为什么我们n的单位是字节。

char*类型的指针每走一步的长度是1个字节,我们可以把传进去的dest和src强制转换为char*类型指针。

这样我么不管传入什么类型的指针,都先用void类型接收,在拷贝时再转换为char类型。

自定义函数my_memcpy实例演示如下:

memcpy函数与memmove函数的自定义实现_数组_04

二、

我们现在想要尝试看看my_memcpy函数能不能实现把数据自身的一部分拷贝给自身,例如下面:

memcpy函数与memmove函数的自定义实现_memcpy_05

能否将2,3,4,5拷贝放在4,5,6,7的位置上。拷贝完后这个数组预期排列是:

1,2,3,2,3,4,5,8,9,10。

下面是演示:

memcpy函数与memmove函数的自定义实现_memcpy_06

我们发现结果并不对,我们用图片来演示以下这个过程:

这是最开始。

memcpy函数与memmove函数的自定义实现_数据_07

第一步。把arr1[1]拷贝给arr1[3]。

memcpy函数与memmove函数的自定义实现_数据_08

第二步,把arr1[2]拷贝给arr1[4]。

memcpy函数与memmove函数的自定义实现_memmove_09

第三步,把arr1[3]拷贝给arr1[5]。

memcpy函数与memmove函数的自定义实现_memmove_10

此时我们发现,arr1[3]由于之前的拷贝已经变为了2,所以此时拷贝给arr1[5]的也是2。

第四步,把arr1[4]拷贝给arr[6]。

memcpy函数与memmove函数的自定义实现_memcpy_11

拷贝结束,此时数组arr1[]={1,2,3,2,3,2,3,8,9,10}。

我们发现,当内存出现重叠的情况下,使用memcpy函数拷贝可能无法达到我们想要的效果。

接下来介绍的memmove函数就可以用来解决这个问题。

三、

memmove函数的声明如下:

memcpy函数与memmove函数的自定义实现_数组_12

memmove函数能够从str2复制n个字节的数据给str1。这一点和memcpy函数

是一致的。但是在str1与str2,出现重叠时,memmove函数更加安全。

memmove函数能够保证str2的数据在被覆盖前复制给str1。

其实memmove函数就是memcpy函数的升级版,它包含了memcpy函数的功能,并且在str1与str2出现重叠时也能实现正常拷贝。

我们再次用memmove函数来拷贝上面提到的数组arr1。

运行结果如下:

memcpy函数与memmove函数的自定义实现_自定义函数_13

我们如愿以偿地让把原本arr1[1],arr1[2],arr1[3],arr1[4]拷贝给了arr1[3],

arr1[4],arr1[5],arr1[6]。

我们想要自定义实现memmove函数,其实就是在我们原本的自定义函数my_memcpy函数的基础上解决掉重叠问题就行了。

memcpy函数与memmove函数的自定义实现_数组_14

我们再来看这个数组,如果想要保证arr1[3]和arr[4]不被覆盖掉,我们可以尝试从后往前拷贝,也就是先把arr[4]拷贝给arr[6],然后把arr[3]拷贝给arr[5],然后把arr[2]拷贝给arr[4],最后把arr[1]拷贝给arr[3]。

从后往前拷贝图示如下:

memcpy函数与memmove函数的自定义实现_数组_15

我们得让dest和src都先指向最后,再向前拷贝。

memcpy函数与memmove函数的自定义实现_memcpy_16

memcpy函数与memmove函数的自定义实现_数据_17

memcpy函数与memmove函数的自定义实现_自定义函数_18

memcpy函数与memmove函数的自定义实现_数据_19

拷贝结束。

按照上面的想法写出下面的代码:

memcpy函数与memmove函数的自定义实现_数组_20

运行结果如下:

memcpy函数与memmove函数的自定义实现_memcpy_21

但是这段代码是有缺陷的,当我们以下图所示的形式拷贝时,就会发生错误。

memcpy函数与memmove函数的自定义实现_数组_22

我们希望拷贝完后的排列是1,2,3,6,7,8,9,8,9,10。

使用my_memmove函数拷贝运行结果如下:

memcpy函数与memmove函数的自定义实现_memcpy_23

并不符合我们的预期,我们发现my_memmove可以实现dest>src的情况,当时无法实现dest<src情况。而想要解决这个问题,只需要从前往后拷贝就好了。

从前往后拷贝图书如下:

memcpy函数与memmove函数的自定义实现_memmove_24

memcpy函数与memmove函数的自定义实现_自定义函数_25

memcpy函数与memmove函数的自定义实现_自定义函数_26

memcpy函数与memmove函数的自定义实现_数据_27

memcpy函数与memmove函数的自定义实现_数组_28

所以我们得分情况,当dest>src时,我们从后往前拷贝,当dest<src时,我们从前往后拷贝,至于dest==src时,两种拷贝方法都行。

最后我们自定义的my_memmove函数代码如下:

memcpy函数与memmove函数的自定义实现_memcpy_29

实例运行结果如下:

dest<src时:

memcpy函数与memmove函数的自定义实现_数组_30

dest>src时:

memcpy函数与memmove函数的自定义实现_自定义函数_31

dest==src时:

memcpy函数与memmove函数的自定义实现_自定义函数_32