memcpy和memmove的区别

我知道它们是在对待重叠区域的时候有所不同,但为什么我看到的很多程序里用的都是memcpy,而不是memmove?我感觉memmove更安全啊,应该推荐使用memmove啊

memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下:
void *memcpy(void *dst, const void *src, size_t count);

void *memmove(void *dst, const void *src, size_t count);

他们的作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。

二者的c语言实现很简单,有兴趣的朋友可以去看看。在实际情况下,这两个函数都是用汇编实现的。

memmove在copy两个有重叠区域的内存时可以保证copy的正确,而memcopy就不行了,但memcopy比memmove的速度要快一些,如:
char s[] = "1234567890";
char* p1 = s;
char* p2 = s+2;
memcpy(p2, p1, 5)与memmove(p2, p1, 5)的结果就可能是不同的,memmove()可以将p1的头5个字符"12345"正确拷贝至p2,而memcpy()的结果就不一定正确了.

和memcpy相比,src和des有重叠的情况下,memmove可以保证数据的完整性.

memmove保证的原因很简单,就是针对重叠的情况做特殊处理,因此速度会比memcpy慢一些

具体的算法并不难想,画个图,分两种情况
1. src的尾部和des的头部重合
从src尾部开始,以地址 -- 的方式copy到des
2. src的头部和des的尾部重合
从src头部开始,以地址 ++ 的方式copy到des
温馨提示:答案为网友推荐,仅供参考
第1个回答  推荐于2017-09-17
memcpy的效率会比memmove高一些,如果还不明白的话可以看一些两者的实现,平时很少有重叠的例子,所以只有特殊情况才考虑memmove

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;
}

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;
}追问

额,平时为什么只有很少会重叠啊?虽然自己感觉也是这样。。

不过这句话倒是说到点子上了。

另外,上面的代码是标准库里的实现代码吗?
对比了一下,除了多了一个判断,对于不重叠的区域,代码其他好像一样啊

追答

平时的memcpy处理的src,dst基本不是一个数组,都是完全不同的东西,完全确定用不着判断的时候为什么还要用memmove?基本就是多了一个判断,虽然效率差不多,但是多了不必要的东西有什么好处吗?

追问

但是如果只是多了一个判断,效率没什么影响,感觉用memmove更安全,不用考虑其他的啊~
不过你说的意思是两个数组的话,就不会重叠了吗?如果是这样的话,就不用纠结了。。。

另外,在用scanf存%s的字符串到字符数组的时候,都不用判断数组大小吗?感觉输入太大的话,数组应该会溢出吧?

追答

两个数组在正常使用(非越界)时不会重叠,scanf字符串超长会移除,所以在无法保证用户输入长度的情况下建议不要使用,可以替换为
if(fgets(line,max,stdin) == NULL)
return 0;

本回答被提问者和网友采纳
第2个回答  2014-04-19
这两个API的出现是因为以前的C API为了讲究效率,一个API少一个内存区是否重叠的判断,效率上会好一点。但由于极容易用错,同时现在来看那点效率并不大。所以很多实现上,他俩的功能已经是完全等价了。追问

就是说以前的话,效率上有些差异的?

追答

对的,以前memmove效率会更高,但必须由使用者确保两个内存区没有交集。但现在已经没有差别。

相关了解……

你可能感兴趣的内容

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 非常风气网