大家好,我学习完memmove函数后做了如下一些总结,和大家一起探讨交流,如有错误和遗漏欢迎大家在评论区指出。
君子性非异也,善假于物也。想要了解一个函数,首先可以利用工具,了解它的基本用法
这里我用www.cplusplus.com这个网站进行查找。
通过这个网站我们可以基本了解到这个函数的作用:
从*source一个字节一个字节的拷贝num个字节到*destination
在学习memmove之前,我们可以先了解一下memcpy,同样通过上面的网站查找:
不难发现,这两个函数的差别好像不大
其实 标准值规定:
memcpy来实现不重叠的内存拷贝;
memmove来实现重叠的内存拷贝。
那么什么是重叠的内存拷贝呢?
int main()//内存里以字节为单位拷贝
{
int arr1[] = { 1,2,3,4,5,6,7,8 };
int sz = sizeof(arr1) / sizeof(arr1[0]);
memmove(arr1, arr1+2, 20);
print(arr1, sz);
return 0;
}
像我这样*source是arr1+2,*destination是arr1,拷贝20个字节,可以发现数组中3,4,5所占的字节重叠了,这就是重叠的内存。
由浅入深,我们先来模拟不重叠的内存拷贝也就是模拟memcpy:
先准备两个数组,写一个打印数组的函数:
#include<stdio.h>
void print(int arr[], int sz)//打印数组的函数
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()//内存里以字节为单位拷贝
{
int arr1[] = { 1,2,3,4,5,6,7,8 };
int arr2[] = { 9,8,7,6,5 };
int sz = sizeof(arr1) / sizeof(arr1[0]);
my_memcpy(arr1, arr2, 16);
print(arr1, sz);
return 0;
}
接下来就是拷贝过程的实现:
其实只要利用循环,将*destination = *source,再都加上1,循环num次,但要注意他们都是void*类型,想要一个字节一个字节的拷贝和进行加减操作的话,必须先把他们强制转换为char*类型:
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* arr3 = dest;
while (num--)
{
*((char*)dest) = *((char*)src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return arr3;
}
最后整个代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void print(int arr[], int sz)//打印数组的函数
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* arr3 = dest;
while (num--)
{
*((char*)dest) = *((char*)src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return arr3;
}
int main()//内存里以字节为单位拷贝
{
int arr1[] = { 1,2,3,4,5,6,7,8 };
int arr2[] = { 9,8,7,6,5 };
int sz = sizeof(arr1) / sizeof(arr1[0]);
my_memcpy(arr1, arr2, 16);
print(arr1, sz);
return 0;
}
运行输出如下:
其实重叠部分的拷贝难点就在于:当进行到重叠部分的拷贝时,可能原始数据已被修改,导致拷贝出错,最简单的解决办法就是将原始数据再放入一块空间记住下来,但是这样就又多占了一块内存,有没有其他更高效的方法呢?
很简单可以分两种情况:
这个时候我们像memcpy一样拷贝可以拷贝完成。
这时候再从前往后拷贝,就会把修改过的数据再次拷贝一份。
解决方法就是不妨试试从后往前拷贝,这样就可以完成,所以最后函数内部代码如下:
void* my_memmove(void* dest, const void* src, size_t num)
{
void* arr3 = dest;
assert(dest && src);
if (dest < src)//从前往后拷贝
{
while (num--)
{
*((char*)dest) = *((char*)src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else if (dest > src)//从后往前拷贝
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return arr3;
}
最后整个代码如下:
#include <stdio.h>
#include<assert.h>
void print(int arr[], int sz)//打印数组的函数
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
void* my_memmove(void* dest, const void* src, size_t num)
{
void* arr3 = dest;
assert(dest && src);
if (dest < src)//从前往后拷贝
{
while (num--)
{
*((char*)dest) = *((char*)src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else if (dest > src)//从后往前拷贝
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return arr3;
}
int main()//内存里以字节为单位拷贝
{
int arr1[] = { 1,2,3,4,5,6,7,8 };
int sz = sizeof(arr1) / sizeof(arr1[0]);
my_memmove(arr1, arr1+2, 20);
print(arr1, sz);
return 0;
}
运行输出如下:
最后拷贝成功。
大家有什么建议或者补充欢迎大家留在评论区,谢谢大家。