C语言中的内存函数有如下这些
- memcpy
- memmove
- memcmp
- memset
下面看看memmove函数
memmove
为什么会需要memmove函数?
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
// 想把12345 拷贝到 34567上去
// 应该打印 1 2 1 2 3 4 5 8 9 10
my_memcpy(arr + 2, arr, 20);
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
// 但是输出 1 2 1 2 1 2 1 8 9 10
return 0;
}
上面会输出 1 2 1 2 1 2 1 8 9 10,我们来看看为什么会出现这样的结果。
我这里画了张图,方便理解。
因为拷贝的地方重叠了,使原来的数据(3 4 5)被覆盖了,导致最后出来的结果不是我们想要的。
也就是说,如果拷贝的地方重叠了,那么就会出现这种情况。
那么如何解决呢?答案就是从后往前拷贝,指针从最后的地方开始操作。
还是上一张图
这样,就得出了我们想要的结果。
但是呢,也不能一概而论,就全部都是从后往前拷贝,还是得分情况的,具体就是看destination
和source
的位置关系。
回到最开始的问题,为什么会需要memmove函数?,因为memmove这个函数可以处理这种重叠拷贝。
老规矩,我们还是看看文档是怎样说的,如下
可以看出,memmove和memcpy的唯一区别就是,memmove函数处理的源内存块和目标内存块是可以重叠的。
也就是说,如果源空间和目标空间出现重叠,就得使用memmove函数处理。
实现
void* my_memmove(void* dest, void* src, size_t num)
{
//dest落在了src的左边,从前往后拷贝
//dest落在了src的右边,同时没有超过那个重叠的边界的时候,从后往前拷贝
assert(dest != NULL);
assert(src != NULL);
void* rest = dest;
// void* 不能直接解引用,那么如何复制呢?
// 给了num个字节,也就是需要复制num个字节
// 那就转换成char*,一个一个字节的复制过去
if (dest < src)
//if (dest < src || dest > (char*)src + num)
{
//dest落在了src的左边,从前往后拷
while (num--)
{
*(char*)dest = *(char*)src;
//++(char*)dest;
//++(char*)src;
((char*)dest)++;
((char*)src)++;
}
}
else
{
// 从后往前拷
// 找到最后一个字节
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return rest;
}
最后,感谢屏幕前的靓仔
花宝贵的时间阅读我这篇博客~
本人水平有限,如有错误以及不足之处,欢迎靓仔
指出。