区别:两个函数都是进行n字节内存内容的拷贝,入口参数和返回参数也都一样,可是这两个函数在内部实现上是有一定区别的,这主要是因为dest内存区域和src内存区域可能有一下四种不同的情况,注意count的影响:
从图中(点击查看全文才能看到图)可以看出,src的内存区域和dest的内存区域相对位置和重叠关系有四种情况,memcpy没有考虑重叠的情况,而memmove考虑到了全部情况,因此memcpy函数的时候可能出现意向不到的结果。
以下是测试它们相同点和区别的程序:
#include <string.h>
int main(void)
{
char src[]="abcdefghijklmnopqrstuvwxyz";
char *dest=src+5;
memcpy(dest,src,8);//case 1,dest>src and overlap,the output is:abcdeabcnopqrstuvwxyz
//memmove(dest,src,8);//case 1,dest>src and overlap,the output is:abcdefghnopqrstuvwxyz
// memcpy(dest,src+7,8);//case 2,src>dest and overlap,the output is: hijklmnonopqrstuvwxyz
// memmove(dest,src+7,8);//case 2,src>dest and overlap,the output is:hijklmnonopqrstuvwxyz
//memcpy(dest,src,3);//case 3,dest>src+count, nonoverlap,the output is:abcijklmnopqrstuvwxyz
//memmove(dest,src,3);//case 3,dest>src+count, nonoverlap,the output is:abcijklmnopqrstuvwxyz
//memcpy(dest,src+10,3);//case 4,src>dest+count and nonoverlap,the output is:klmijklmnopqrstuvwxyz
//memmove(dest,src+10,3);//case 4,src>dest+count and nonoverlap,the output is:klmijklmnopqrstuvwxyz
printf("\nThe result is:\n%s",dest);
return 0;
}
从输出可以看出,这两个函数只有在情况1时不同,主要是因为memcpy没有考虑重叠时的情况,导致src内存并不是原来的内容,而在运行过程中被修改过了。可以看出,使用memmove更具通用性,但是运行速度会慢一点。
这两个函数的实现:
void *memcpy(void *src,void *dest,size_t count)
{
void *pret=dest;
while(count--)
*dest++=*src++;
return pret;
}
void *memmove(void *src,void *dest,size_t count)
{
void *pret=dest;
if(src<dest+count)//case 1,copy backward prevent from modifying source data before copy.
{
src=src+count-1;
dest=dest+count-1;
while(count--)
*dest--=*src--;
}
else
{
while(count--)
*dest++=*src++;
}
return pret;
}
|
图的上半部分为源内存区域在目标内存区域右边,下半部分为源内存区域在目标区域左边,源内存区域和目标内存区域都有交叉。
memcpy()是从src的起始部分开始复制,所以虽然第一种情况下没有问题,但如果遇到第二种情况,则会发生错误,如图所示,后两个字节在被复制前已经被覆盖掉了。而memmove()则由于采用了不同的复制机制,所以可以正确处理第二种情况。
VS.NET2003中所附源码如下(有删):
|
|