首先两者均是来自<string.h>的函数,然后两者的区别在于memcpy的功能没有memmove完善,memmove不仅能实现memcpy的功能,并且还能实现在源空间与目标空间重叠的情况下,依旧能够进行复制,详细原因见下文。
一、作用
memcpy:
可以将soure位置开始num个字节大小的内存块复制到destination位置
例:
即memcpy可以将arr1该地址后20个字节的数据复制到arr2位置(一个int类型占4个字节)
结果:
可以看到arr2数组内被放入了arr1地址后20个字节的数据
自实现代码;
void* my_memcpy(void* dest, void* str, size_t num)
{
assert(dest);//空指针检测
assert(str);
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)str;
dest = (char*)dest + 1;
str = (char*)str + 1;
}
return ret;
}
memmove:
可以将soure位置开始num个字节大小的内存块复制到destination位置,并且soure位置内存块可以与destination位置内存块重叠。
例:
即memmove可以将arr1该地址后20个字节的数据复制到arr1+2位置(一个int类型占4个字节)
结果
可以看到原本位置的3,4,5,6,7已经被覆盖成了1,2,3,4,5
自实现代码:
void* my_memmove(void* dest, void* str, size_t num)
{
assert(dest);//空指针检测
assert(str);
void* ret = dest;
if (dest < str)
{
while (num--)
{
*(char*)dest = *(char*)str;
dest = (char*)dest + 1;
str = (char*)str + 1;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)str + num);
}
}
return ret;
}
二、区别
开头已经说明了区别,但这区别从何而来?
简单看个图各位就明白了(以目标空间在源空间后为例)
红:目标空间 绿:源空间
可以看到因为源空间与目标空间的重叠,第一次复制虽然将目标空间的第一个位置复制成了1,但同时也将源空间的第二个位置变成了1,当第二次复制时,因为源空间第二个位置是1,所以目标空间的第二个位置变成了1,显然这样下去肯定不会得到我们想要的结果。
于是为了解决这个问题,我们发现从源空间的最后往前复制不会出现源空间值还未被复制过便被更改的情况(若目标空间在源空间前,则从前往后复制。即目后复后,目前复前)
红:目标空间 绿:源空间
因此memmove就此诞生,解决了memcpy的重叠问题,从memcpy一个普通的男人变成了memmove一个帅气的男人。