memcpy和memmove 的功能都是将一块空间的数据拷贝到另一块空间中 但是二者的实现还是有点区别的
void *memcpy( void *dest, const void *src, size_t count );
void *memmove( void *dest, const void *src, size_t count );
功能概述:把源头指针src开始往后的size_t个字节的内容拷贝到目的地指针dest往后的size_t个字节空间中
可见这两个函数的参数 和返回类型都是一样的 表面似乎没有区别 只是名字不同 但是实质上memmove的功能包括了memcpy的功能 memcpy 可以看作是memmove的子集
假如有一个字符串
我们要实现从把紫色框里的内容拷贝到红框中 那么我们想当然的结果应该是 ababcdfg
但是用memcpy处理后的结果是下面这样的(在VS2019中memcyp已经做了优化 函数的功能和memmove已经是一模一样的了,这里主要是讲的是memcpy未优化前的功能与memmove的区别)
代码如下
void* mymemcpy(void* dest, const void* src, int sz)
{
assert(dest && src);
void* ret = dest;
while (sz--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
根据代码我们知道 memcpy的实现是把 src(先转化为char*)指向的内容赋值给dest(先转化为char*)指向的内容 然后两个指针都往后移动一个字节 这样操作size_t次
这种方法实现会有一个不足的地方就是当两块空间有重叠的地方就会出错 原数据会在未被拷贝到目的位置之前被覆盖掉 就像上面的cd 被ab覆盖掉 导致cd无法按照我们的想法被拷贝到g之前
而memmove则解决了这一缺点
根据上图可以得出一个规律 :
当dest大于src的时候 我们从后往前拷贝(将src的最后一个数据赋值给dest的最后一个数据 指针在往前走)
当dest小于src的时候 我们从前往后拷贝
按照这个规律就可以完美解决两块空间有重叠会处理不好的情况
void* mymemmove(void* dest, const void* src, int sz)
{
assert(dest && src);
void* ret = dest;
if (dest < src)//分两种情况 dest在src前 和dest 在src后 情况不同拷贝的顺序不同 一个是从前往后 一个是从后往前
{
while (sz--)//这里的sz--是先判断sz是否满足循环进行的条件 满足后再自减 在进入循环 进入循环后sz的大小是减了1的
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)dest + 1;
}
}
else//这种情况就是从后往前拷贝了
{
while (sz--)
{
*((char*)dest + sz) = *((char*)src + sz);
}
}
return ret;
}