memmove 解决内存拷贝时内存重叠的问题

本文详细解释了内存拷贝中常见的strcpy、memcpy与memmove函数的区别,重点在于如何处理内存重叠的问题,通过代码示例说明了不同情况下这些函数的行为。

内存重叠:拷贝的目的地址在源地址范围内。所谓内存重叠就是拷贝的目的地址和源地址有重叠。

在函数strcpy和函数memcpy都没有对内存重叠做处理的,使用这两个函数的时候只有程序员自己保证源地址和目标地址不重叠。

使用memmove函数可解决内存重叠问题。memmove函数对内存重叠做了处理。


重叠从两方面考虑:

(1).dest数据覆盖了source; 如:dest(8byte) 地址:1000

source(8byte) 地址:1002

(2).dest所指的区域本来就是source的一部分; 如:dest(8byte) 地址:1000

source(8byte) 地址:0998

例如:针对第一种交叉情况情况,dst<src且dst+count>src,memcpy和memmove的结果是一样的。请看下面的例子讲解:

string s = "hello world";

memmove(&s[0],&s[5],10);



1.下面来看strcpy(): 字符串拷贝. 

char *strcpy(char *strDest, const char *strSrc)
{
assert((strDest!=NULL) && (strSrc !=NULL));
char *address = strDest; 
while( (*strDest++ = * strSrc++) != '\0') 
   ; 
return address ; 
}

2.下面来看下memcpy函数:内存拷贝

void *memcpy(void *dest, const void *source, size_t count)
{
   assert((NULL != dest) && (NULL != source));

   char *tmp_dest = (char *)dest;
   char *tmp_source = (char *)source;
   while(count --)//不对是否存在重叠区域进行判断
       *tmp_dest ++ = *tmp_source ++;
   return dest;
}

3.下面来看下memmove函数:

void* _memmove(void* dest, const void* src, size_t count)
{
	assert(src != nullptr && dest != nullptr);
	char* tmp_dest = (char*)dest;
	const char* tmp_src = (const char*)src;

	if (tmp_src < tmp_dest)//当src地址小于dest地址时,从后向前拷贝,保证dest数据正确
	{
		tmp_src += count - 1;
		tmp_dest += count - 1;
		while (count--)
			*tmp_dest-- = *tmp_src--;
	}
		
	else if (tmp_src > tmp_dest)//当src地址大于dest地址时,从前向后拷贝,保证dest数据正确
	{
		while (count--)
			*tmp_dest++ = *tmp_src++;
	}
	//else(tmp_src==tmp_dest) 此时不进行任何操作
	return dest;
}

以上是我自己的理解,下面是百度的别人的代码,有待研究:

void *memmove(void *dest, const void *source, size_t count)
{
assert((NULL != dest) && (NULL != source));
char *tmp_source, *tmp_dest;
tmp_source = (char *)source;
tmp_dest = (char *)dest;
if((dest + count<source) || (source + count) <dest))
{// 如果没有重叠区域
while(count--)
*tmp_dest++ = *tmp_source++;
}
else
{ //如果有重叠(反向拷贝)
tmp_source += count - 1;
tmp_dest += count - 1;
while(count--)
*--tmp_dest = *--tmp;
}
return dest;
}


...


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值