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不保障拷贝的后果的正确。
第一种状况下,拷贝重叠的区域不会呈现问题,内容均能够正确的被拷贝。
第二种状况下,问题呈现在左边的两个字节,这两个字节的原来的内容首先就被笼罩了,而且没有保留。所以接下来拷贝的时候,拷贝的是曾经被笼罩的内容,显然这是有问题的。
实际上,memcpy只是memmove的一个子集。
二者的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内存拷贝,没有问题;memmove,内存挪动?错,如果这样了解的话,那么这篇文章你就必须要好好看看了,memmove还是内存拷贝。那么既然memcpy和memmove二者都是内存拷贝,那二者到底有什么区别呢?
先说memcpy
你有没有好好的加入过一场C++口试。让你写出memcpy的实现,这是如许常见的口试题啊。当初,拿起你的演算纸和笔;是的,是笔和纸,不是让你在你的IDE上写。写不进去?看上面吧:
void *memcpy(void *dest, const void *src, size_t count){assert(dest != NULL || src != NULL);char *tmp = (char *)dest;char *p = (char *)src;while (count--){*tmp++ = *p++;}return dest;}
memcpy的实现很简略,个别在口试时,呈现写源码的题目,无非就是须要留神以下几点:
1.确定函数原型;
2.判断参数合法性;
3.逻辑实现(思考各种状况,统称逻辑实现);
4.错误处理。
当然了,我的这个没有错误处理,也不须要错误处理。下面,我写出了memcpy的实现源码,实现原理如下图所示:
这样上来,下面的代码会运行的很好,如果呈现上面的状况呢?
i、n、k的内存和J、e、l的内存地址重合了,当初再应用下面的代码进行copy时,会呈现什么问题呢?你有没有想过这个问题。如果没有,那就当初想想,不急着浏览上面的内容。
而后,我再留一个问题,下面的代码中,为什么都须要将void 转换成char 呢?比方:char *tmp = (char *)dest;
再说memmove
memmove也是用来实现内存的间接拷贝的。说起这个命名,我集体觉的多少还是有点坑的。既然memmove也是用来内存数据挪动的,那就先来看看memmove的实现源码。
void *memmove(void *dest, const void *src, size_t count){assert(dest != NULL || src != NULL)if (dst < src){char *p = (char *)dest;char *q = (char *)src;while (count--){*p++ = *q++;}}else{char *p = (char *)dest + count;char *q = (char *)src + count;while (count--){*--p = *--q;}}return dest;}
从源码看,memmove确实比memcpy简单一些;再认真一看,多了些什么?哦,多了一个else分支,而正是这个else分支,就解决了当src和dest的内存重合的问题。
memcpy和memmove的比拟
从实现源码中确实能看出一些猫腻,当呈现了src和dest的内存有重合的机会时,memmove的解决规定是从后往前进行copy。当然了,重合的问题,须要思考的以下两种场合。
如图所示,当呈现(1)对应的状况时,就须要先从src的头部开始复制;也就是memmove源码中的if分支,这部分源码和memcpy的实现是统一的;当呈现(2)对应的状况时,就须要先从src的尾部开始复制,防止出现了笼罩景象。这就是memmove比memcpy多的一个思考点,所以说,在理论应用时,应用memmove是比memcpy更平安的。