memmove和memcpy区别

memmove和memcpy区别


     memcpy()和memmove()都是c语言的库函数(头文件保护#include <string.h>),作用是拷贝一定长度内存的内容。它们唯一的区别是当内存发生局部重叠时,memmove可以保证拷贝正确,memcpy拷贝的结果是未定义的(取决于编译平台内部对memcpy的优化处理)。函数声明如下:

void * memmove(void * dst, void * src, size_t count)
void * memcpy(void * dst, void * src, size_t count)

     dst:目的地址
     src:源地址
     count:拷贝的字节数

     Memcpy的实现代码如下:
在这里插入图片描述
     可以看到,memcpy内部实现只是单纯的进行地址内容的赋值操作,并没有对重叠区域进行处理。这就会导致到dst和src的地址存在重叠时,拷贝异常。

     重叠区域主要分为两种情况,dst地址高于src地址和dst地址低于src地址,下面对这两种情况分别介绍:
1, dst地址低于src地址
     见下图,当dst地址低于src地址时,拷贝src地址开始count个字节到dst地址中,不会存在拷贝覆盖的情况,拷贝正常。
在这里插入图片描述
2, dst地址高于src地址
     dst地址高于src地址又可以分为两种情况,dst-src >= ncount和dst-src < ncount。
     2.1,dst-src >= ncount
在这里插入图片描述
     当dst与src的地址差大于等于ncount时,从src拷贝ncount个字节到dst地址中,也不会存在地址重叠情况,拷贝正常。

     2.2 dst-src < ncount
在这里插入图片描述
     如图所示,当dst地址高于src地址,且重叠区域在ncount范围内时,src第一次拷贝src1到dst1时,覆盖了src4,导致后面再将src4拷贝到dst4时,并不是原有的src4值,此种地址重叠情况,会导致拷贝结果不正确。

     再看memmove的实现:
在这里插入图片描述
     对于我们上述分析的情况1和情况2.1,memmove的处理和memcpy是一样的,但是对于2.2的地址重叠情况,memmove使用了一个else分支处理,处理逻辑也很简单,对于src和dst都是从高地址到低地址遍历拷贝,这样就避免了高地址的覆盖情况。

     我们以下面这个例子进行实例验证:

void * mymemcpy(void * dst, void * src, size_t count)
{
	void * ret = dst;

	while (count--)
	{
		*(char*)dst = *(char*)src;
		dst = (char *)dst + 1;
		src = (char *)src + 1;
	}

	return(ret);
	
}

int main()
{
	char a[8] = "abcdefg";

	memcpy(&a[1], &a[0], 4);
	std::cout << "memcpy a = " << a << std::endl;

	strcpy_s(a, sizeof("abcdefg"), "abcdefg");
	mymemcpy(&a[1], &a[0], 4);
	std::cout << "mymemcpy a = " << a << std::endl;

	strcpy_s(a, sizeof("abcdefg"), "abcdefg");
	memmove(&a[1], &a[0], 4);		
	std::cout << "memmove a = " << a << std::endl;

	system("pause");
    return 0;
}

     输出结果如图:
在这里插入图片描述
     可以看到使用内置的memcpy的输出结果和memmove结果一样,但是使用我们自己实现的mymemcpy,却是输出了正确的结果(正确是指:memcpy逻辑本应输出的结果),我使用的编译器是vs2015,在VC6.0编译环境下也是一样的输出结果,这是由于memcpy是一个由编译器实现的函数,编译器内部对它进行了优化处理,导致对重叠区域的地址拷贝会出现未定义结果。
     查阅资料发现有很多人都说memcpy性能远高于memmove,我在windows平台,vs2015环境下测试,两者性能几乎无差别,所以在此环境下,可以直接使用memmove,也避免了考虑使用memcpy带来的重叠区域的未定义现象。

  • 19
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Simple Simple

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值