memcpy
概念与使用
- 实现这个函数之前我们先认识一下这个函数
void * memcpy ( void * destination, const void * source, size_t num );
- 这个函数的作用就是将source后的num个字节的数据保存到destination的内存位置
- 注意:destination和source是不可以出现重叠的
具体实现的例子:
#include<stdio.h>
int main()
{
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int arr2[20] = { 0 };
memcpy(arr2, arr1, 8);
int i = 0;
for (i = 0; i < 20; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
- 由上面可以看到我们使用memcpy函数将arr1(source)的内容保存到了arr2(destination)的位置,因为num是8数组元素的类型是int,所以只有前俩个元素被替换
自主模拟实现(my_memcpy)
思路:
1.函数传参的三个值分别为目的地地值,源头地址和想要复制到目的地的元素的字节数(这里注意是字节数),所以传参时形参类型分别为(void*,void*,size_t)
(void*)是因为不知道传过来的是什么类型的指针所以用void*来接收比较合适
size_t是为了确保传过来的数不是负数
2.根据函数相关概念我们可以了解到函数的返回值是void*
3.了解到函数可以直接将源头的数据复制到目的地,还可以规定复制的字节数,所以这里我们可以用while循环来解决,循环条件为(num–)这样等想要的字节数复制完了以后循环自然而然就停止了
4.想到(void*)是不能被解引用的,那么用什么比较合适呢,既然我们要实现的函数是一个字节一个字节替换,那么用(char*)就比较合适
接下来是函数实现案例:
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest && src);//断言防止传来的指针为空指针
void* ret = dest;//将dest的起始位置付给ret
while (num--)
{
*(char*)dest = *(char*)src;//将第一个字节的内容复制给dest
dest = (char*)dest + 1;//指针位置加一指向下一个字节
src = (char*)src + 1;
}
return ret;
}
memmove
概念与使用
- 同样我们先认识一下这个函数
、void * memmove ( void * destination, const void * source, size_t num );
- 这个函数和上一个函数的区别就在于memmove处理的源和目标是可以重叠的
例子:
int main()
{
int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
memmove(arr1 + 2, arr1, 8);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
- 由上面我们可以看到函数将1,2复制到了3,4的位置上,这就说明了memmove允许在源和目标重叠的情况下进行和memcoy一样的操作
自主模拟实现(my_memmove)
思路与上面不同的是我们要解决重叠时还可以进行复制的功能
-
我们可以想到如果这时还用上一个函数的方法是不能达到目的的,如果dest在src前面(dest的地址相较于src更低),当我们从前向后并不能达到目的,这时我们就不得不考虑一下换个方法,从后往前就比较适合,不会出现想要替换的数被覆盖的情况
-
根据上面我们能分析出,当dest<src时用从前往后的方法,其余情况就用从后往前,这样就解决了被覆盖的问题
-
代码如下:
void* my_memove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
if (src > dest)
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);//从后往前
}
}
return ret;
}