memcpy与memmove的区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了memcpy与memmove的区别相关的知识,希望对你有一定的参考价值。
参考技术A memcpy和memmove都是C语言的库函数,相比于strcpy和strncpy只能拷贝字符串数组,memcpy与memmove可以拷贝其它类型的数组,但是为什么要同时提供两种方法呢?本文主要就是介绍这两个函数的区别。首先来看函数原型:
这两个函数都是将s2指向位置的n字节数据拷贝到s1指向的位置,区别就在于关键字restrict, memcpy假定两块内存区域没有数据重叠,而memmove没有这个前提条件。如果复制的两个区域存在重叠时使用memcpy,其结果是不可预知的,有可能成功也有可能失败的,所以如果使用了memcpy,程序员自身必须确保两块内存没有重叠部分。
我们来看一组示例:
正常情况下,即使内容有重叠,src的内容也可以正确地被拷贝到了dest指向的空间。
这种情况下,src的地址小于dest的地址,拷贝前3个字节没问题,但是拷贝第4,5个字节时,原有的内容已经被src拷贝过来的字符覆盖了,所以已经丢失原来src的内容,这很明显就是问题所在。
一般来说,memcpy的实现非常简单,只需要顺序的循环,把字节一个一个从src拷贝到dest就行:
memmove会对拷贝的数据作检查,确保内存没有覆盖,如果发现会覆盖数据,简单的实现是调转开始拷贝的位置,从尾部开始拷贝:
这里 __np_anyptrlt 是一个简单的宏,用于结合拷贝的长度检测dest与src的位置,如果dest和src指向同样的对象,且src比dest地址小,就需要从尾部开始拷贝。否则就和memcpy处理相同。
但是实际在C99实现中,是将内容拷贝到临时空间,再拷贝到目标地址中:
由此可见memcpy的速度比memmove快一点,如果使用者可以确定内存不会重叠,则可以选用memcpy,否则memmove更安全一些。另外一个提示是第三个参数是拷贝的长度,如果你是拷贝10个double类型的数值,要写成sizeof(double)*10,而不仅仅是10。
memcpy memmove区别和实现(转)
memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中。
但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开销。
memmove的处理措施:
(1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
(2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝
(3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝
-- memcpy实现
void* memcpy(void* dest, const void* src, size_t n) { char* d = (char*) dest; const char* s = (const char*) src; while(n-–) *d++ = *s++; return dest; }
-- memmove实现
void* memmove(void* dest, const void* src, size_t n) { char* d = (char*) dest; const char* s = (const char*) src; if (s>d) { // start at beginning of s while (n--) *d++ = *s++; } else if (s<d) { // start at end of s d = d+n-1; s = s+n-1; while (n--) *d-- = *s--; } return dest; }
示意图:
(1)内存低端 <-----s-----> <-----d-----> 内存高端 start at end of s (2)内存低端 <-----s--<==>--d-----> 内存高端 start at end of s (3)内存低端 <-----sd-----> 内存高端 do nothing (4)内存低端 <-----d--<==>--s-----> 内存高端 start at beginning of s (5)内存低端 <-----d-----> <-----s-----> 内存高端 start at beginning of s
转自:https://www.cnblogs.com/kekec/archive/2011/07/22/2114107.html
以上是关于memcpy与memmove的区别的主要内容,如果未能解决你的问题,请参考以下文章