在之前我们学习过strcpy函数,这个函数能完成对一个字符串的拷贝那么有没有一个函数能完成对所有类型数据数组的拷贝呢?当然是有的那就是memcpy
下面我们就来看一下这个函数的使用
#include<stdio.h>
#include<string.h>
void print_arr(int arr1[], int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", arr1[i]);
}
printf("\n");
}//这是我写的一个打印数组的函数
int main()
{
int arr[] = { 1,4,7,8,5,2,3,6,9 };
int arr1[5] = { 0 };
int sz2 = sizeof(arr) / sizeof(arr[0]);
print_arr(arr, sz2);
memcpy(arr1, arr, 20);//这里的意思就是将arr所在的空间里的20个字节的数据复制的arr1所在的空间里
int sz = sizeof(arr1) / sizeof(arr1[0]);
print_arr(arr1, sz);
return 0;
}
运行截图如图下因为一个整型是四个字节大小所以20字节也就是5个整型,所以这里就将arr里的5个元素拷贝到了arr1里面。
下面我们来模拟实现这个函数
#include<stdio.h>
#include<assert.h>
void printf_arr(int arr[], int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void* my_memcpy(void* des, const void* sor, size_t num)//因为这个函数能拷贝的是所有的数据类型
//所以创建的就是void* 类型的指针void* 指针的特点就是能够接受所有的数据类型的地址,但是不能进行解引用
//以及加减操作
{
assert(des && sor);
void* ret = des;//这里创建一个void*类型的指针方便之后返回
while (num--)//这里的num就是要拷贝的字节数
{
*(char*)des = *(char*)sor;//这里就像将其强制类型转换为char*类型的指针然后解引用
//因为char的字节为1个字节所以不论是什么类型的数据最后都能完成拷贝
des = (char*)des + 1;//因为强制类型转换是暂时的所以运用这种方式完成des和sor指针的前移
sor = (char*)sor + 1;
}//这里要这么写,是因为强制类型转换只是暂时的,当我们通过强制类型转换赋值之后,还要让其++
//但是如果和下面的这两种
return des;
}
int main()
{
int arr[] = { 1,4,7,8,5,2,3,6,9 };
int arr1[5] = { 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
printf_arr(arr, sz);
my_memcpy(arr1, arr, 20);
sz = sizeof(arr1) / sizeof(arr1[0]);
printf_arr(arr1, sz);
return 0;
}
运行截图和上图一致
,再学了这个代码后我们想一下假设有一个数组名为1 2 3 4 5 6 7 8 9,若我们想将2 3 4 5拷贝到4 5 6 7上让数组变为1 2 3 2 3 4 5 7 8 9。如果我们使用memcpy函数的话,最后打印出的数组可能是这样的:1 2 3 2 3 2 3 8 9,那为什么会出现这种情况呢?我们来分析一下当我们将2拷贝到4后,4就被覆盖成了2,3也就拷贝到了5的位置,5也就被覆盖成了3当我们要拷贝4的时候,4已经被覆盖成了2,2再次被拷贝,同理5也是。
那么有没有一个函数能完成这个功能呢?那就是memmove
下图就是memmove为什么能完成这个功能的原因
下面我们就用一个代码来看这个函数的应用
这个代码的目的就是7 8 5 2 3拷贝到 1 4 7 8 5
#include<stdio.h>
#include<string.h>
int main()
{
int arr[] = { 1,4,7,8,5,2,3,6,9 };
memmove(arr, arr + 2, 20);//因为数组名在一般情况下是数组首元素的地址,所以首元素的地址加2就指向了7
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}//这里之所以不能运用memcpy是因为memcpy只有从前向后拷贝这一种方式,但是在拷贝重叠内存的时候即需要从前向后拷贝的方式,也需要从后向前拷贝的方式
return 0;
}
下面我们就来模拟实现这个函数
#include<stdio.h>
#include<assert.h>
void* my_memmove(void* des, const void* sor, size_t num)
{
void* ret = des;
assert(des && sor);
while (num--)
{
if ((char*)des < (char*)sor)
{
*(char*)des = *(char*)sor;
des = (char*)des + 1;
sor = (char*)sor + 1;
}//这是从前向后拷贝
else//下面是从后向前拷贝
{
*((char*)des + num) = *((char*)sor + num);
}
}
return ret;
}
int main()
{
int arr[] = { 1,4,7,8,5,2,3,6,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
my_memmove(arr, arr + 2, 20);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
运行截图也和上面一样。
最后我们来学习memset函数。
#include<stdio.h>
#include<string.h>
int main()
{
int arr[10] = { 1,1,1,1,1,1,1,1,1,1, };
memset(arr, 0, 20);
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
printf("%d", arr[i]);
}
return 0;
}
从运行截图我们也就能知道这个函数的功能了。
它能将中间的符号初始化到数组里面,初始化的数量就是20个字节的空间。
下面我们来模拟实现这个函数
#include<stdio.h>
#include<assert.h>
void* my_memset(void* des, int va, size_t num)
{
assert(des);
char* ret = des;
while (num--)
{
*(char*)des = va;
des = (char*)des + 1;
}
return ret;
}
int main()
{
int arr[10] = { 1,1,1,1,1,1,1,1,1,1, };
my_memset(arr, 0, 20);
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
printf("%d", arr[i]);
}
return 0;
}
希望这篇博客能对你有所帮助,若有错误,请严厉指出我一定改正。