memcpy:指的是c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
函数原型:void *memcpy(void *dest, const void *src, size_t n);
memmove:memmove用于从src拷贝count个字节到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。但复制后src内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同。
函数原型:void *memmove(void *dst, const void *src, size_t count);
两者区别:
函数memcpy() 从source 指向的区域向dest指向的区域复制count个字符,如果两数组重叠,不定义该函数的行为,而memmove(),如果两函数重叠,赋值仍正确进行。
总结:两者的功能基本相同,唯一不同的是,当 dest 和 src 有重叠的时候选用不同的函数可能会造成不同的结果。
1. 当 src 和 dest 所指内存区有重叠时,memmove 相对 memcpy 能提供保证能将 src 所指内存区的前 n 个字节正确的拷贝到 dest 所指内存中;
2. 当 src 地址比 dest 地址低时,两者结果一样。换句话说,memmove 与 memcpy 的区别仅仅体现在 dest 的头部和 src 的尾部有重叠的情况下;
即:从高向低复制都可以,从低向高复制用memmove()
memcpy的返回值设计成void *是有目的的,是便于嵌套使用memcpy、memmove等函数。
两者的实现:
《一》memmove
void *MemMove(void *dest,const void *src,size_t n)
{
if(n == 0)
return 0;
if(dest == NULL)
return 0;
if(src == NULL)
return 0;
char *psrc = (char*)src;
char *pdest = (char*)dest;
//检查是否有重叠问题
if((dest <= psrc) || (pdest >= psrc+n))
{
for(int i=0;i<n;i++)
{
*pdest = *psrc;
psrc++;
pdest++;
}
}
else
{
psrc += n;
pdest += n;
for(int i=0;i<n;i++)
{
psrc--;
pdest--;
*pdest = *psrc;
}
}
return dest;
}
《二》memcopy
void *MemCopy(void *dest,const void *src,size_t n)
{
if(NULL == dest)
return 0;
if(NULL == src)
return 0;
char *pdest = (char*)dest;
char *psrc = (char*)src;
while(n--) //不对是否存在重叠区域进行判断
{
*pdest++ = *psrc++;
}
return dest;
}
要想安全的使用memcopy函数,必须要解决内存重叠。所以最完美的解决方案还是判断源地址和目的地址的大小,才决定到底是从高地址开始拷贝还是低地址开始拷贝。改进后的代码如下:
void * MyMemMove(void *dst,const void *src,int count)
{
assert(dst);
assert(src);
void * ret = dst;
char *psrc = (char*)src;
char *pdest = (char*)dest;
//判断是否有内存重叠
if (pdest<= psrc || pdest>= (psrc+ count)) {
while (count--) {
*pdest= *psrc;
pdest++;
psrc++;
}
}
else {
pdest= pdest+ count - 1;
psrc= psrc+ count - 1;
while (count--) {
*pdest= *psrc;
pdest--;
psrc--;
}
}
return(ret);
}