memcpy与memmove的区别

Python013

memcpy与memmove的区别,第1张

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()都是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