memmove函数是一个可以拷贝字节的函数,不像strcpy函数一样有类型限制,memmove可以接受任意类型的指针。如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同,是memcpy函数的升级版。
函数有三个参数,分别是目的地地址、源地址、要拷贝的字节数,为了能处理各种类型的数据,参数地址的类型要是void*。首先不要忘记断言以判断指针的有效性,因为要拷贝至目的地,所以最后要返回目的地地址,为防止执行过程中丢失目的地起始地址,先用ret接收目的地起始地址,最后返回ret即可。首先会想到从前向后一位位字节拷贝(因为拷贝的单位是字节,所以要记得强制类型转换),但是如果源区域和要拷贝的区域有重叠的话,代码就会出错,部分数据会被覆盖。观察发现比较源地址和目的地起始地址是关键,如果源地址大于目的地地址,这时从前向后拷贝不会发生覆盖,而如果源地址小于目的地地址,从前向后便不行了,这时需要从后向前拷贝。
分析清楚之后,便可以写代码了。从前向后:拷贝一次num自减一次,直到为0停止,每一次拷贝后源地址和目标地址自加;从后向前:即从最后一个字节开始拷贝,因为num自减了一次,所以找位置时(char*)src + num刚好指向最后一个字节。这样便可以完美拷贝,不管是什么情况都能应付。
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
if (dest < src)
{
//前-->后
while (num--)
{
*(char*)dest = *(char*)src;
++(char*)src;
++(char*)dest;
}
}
else//后-->前
{
while (num--)
*((char*)dest + num) = *((char*)src + num);
}
return ret;
}