模拟内存拷贝函数:memcpy memmove

1. 题目一:不使用库函数,模拟实现内存拷贝函数memcpy的功能。

分析:

memcpy与strcpy不同,它是以字节为单位进行拷贝,每次拷贝一个字节,使用时,需要了解要拷贝的字节数。同时,因为它是以字节进行拷贝,所以无类型限制,即对任意类型均可以使用,而strcpy专用于字符串。

它的拷贝原理与strcpy类似,strcpy以“\0”为结束判断依据,而memcpy以要拷贝的字节数为结束判断依据。

代码如下:

模拟内存拷贝函数:memcpy memmove

例一:将src拷贝到dest中,主函数代码:

模拟内存拷贝函数:memcpy memmove

运行结果:

模拟内存拷贝函数:memcpy memmove

例二:当希望将src中的后续字符依次前移时,希望得到“xjgqg”时,主函数变为如下:

模拟内存拷贝函数:memcpy memmove

运行结果:

模拟内存拷贝函数:memcpy memmove

显然,与我们预期一致。

例三:当希望将src中的字符依次后移时,希望得到“bbxjgq”时,主函数变为如下:

模拟内存拷贝函数:memcpy memmove

此时,运行结果为:

模拟内存拷贝函数:memcpy memmove

这显然与我们预期的结果不同。此时,memcpy的功能已经不再适用,这里就需要用到memmove。

2. 题目二:模拟实现内存拷贝函数memmove的功能

同样是内存拷贝函数,两者之间的区别是什么呢?

这里,我们分析下两个字符串拷贝的几种情况:src表示源字符串,dest表示目标字符串。(因为dest是目标字符串,所以dest的长度一定大于src的长度)

1)src的地址小于dest的地址,二者不重叠。

2)src的地址大于dest的地址,二者不重叠。

3)src的地址小于dest的地址,二者不重叠。

4)src的地址小于dest的地址,二者有重叠(包括src完全包含在dest中的情况)。

如下图:

模拟内存拷贝函数:memcpy memmove

在处理前无重叠情况时,memcpy是适用的。再由上述例二,例三知,情形三memcpy也是适用的,而memcpy不适用于情形四。

而memmove就是用于解决情形四的,更确切的说,它对这四种情形都适用。前三种情形可以用与memcoy相同的方法接解决,

那么,情形四如何解决呢?

分析:

首先,我们需要知道上述例三的结果是如何产生的,在就上图而言,当src向dest拷贝时,a先拷给d,b拷给e,c拷给f,当要将d拷给g时,发现原来的有效d已经被a替代,使之失效 ,所以结果会变为abcabca,与例三的的结果类似。

其次,知道了出错原因,如何解决呢,上述叙述中,是从左往右拷贝的,这里,我们需要从右往左拷贝,即先拷贝g,依次往左进行,即使后面的拷贝会覆盖g但g已经发挥起作用,已经失效,所以,可以从右往左拷。

然后,src,dest初始是在字符串开头,那么需要移到右边什么地方呢?这时,就要考虑需拷贝的字节数了,若需拷贝k个字节,则src,dest分别从src+k,dest+k开始,依次往左拷。

最后,我们考虑下情形四的条件,从图中,可以观察到,src<dest且src+strlen(src)>dest。而其余情形方法与memcpy相同。

通过分析,代码编写如下:

模拟内存拷贝函数:memcpy memmove

对上述例三进行验证:

模拟内存拷贝函数:memcpy memmove

运行结果:

模拟内存拷贝函数:memcpy memmove

可以看到,结果与预期一致。

注意:

在对字符串进行拷贝时,首选strcpy;

在对内存进行拷贝时,可以选取memmove和memcpy,

而memmove的功能是兼容memcpy的,在检测字符串是否重叠时,就可以选择memcpy。