1.memcpy
memcpy是从src的位置开始向后复制count个字节的数据到dest指向的内存空间
首先解读一下这个库函数的整体形式
memcpy的返回类型是空指针,参数是两个空指针,所需要包含的头文件分别是<string.h>
需要注意的是
这个函数在遇到 '\0' 的时候并不会停下来。
举个例子
#include <string.h>
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 5*sizeof(arr1[0]));
int i = 0;
for (i = 0; i < 10; i++)//打印
{
printf("%d ", arr2[i]);
}
return 0;
}
我们定义两个整形数字第一个数组里存放1~10 第二个数组全部初始化为0,通过我们的memcpy函数将arr1中的数字拷贝到arr2中的数组中,后边的第三个参数就是我们要重点说的地方
5*sizeof(arr[0]) 中的sizeof是计算我们的整形也就是int类型的字节大小,int的字节大小是4,5*4也就是20个字节,然而我们的memcpy函数也是通过字节的个数,来访问我们的电脑因该拷贝多少个字节。综上所述那20字节也就是5个数字那arr2中的数组应该就是前五个0变成1~5,来看结果。
接下来我们就模拟实现一下memcpy来更加透彻的理解这个库函数,注意是模拟实现
模拟实现memcpy
void* My_memcpy(void* dest, void* src, size_t count)
{
void* ret = dest;
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
参数和原来的得参数保持一致,首先我们上来就count--让我们执行的循环次数和我们传递过去的字节数保持一直,当我们的字节数是0时整个循环就会终止。也就是我们拷贝了多少个字节,内部的构造就比较简单,我们要明白的是void*是一个空指针不能直接进行解引用操作,所以我们强制类型转换将它改为char*类型再进行解引用操作,这样就可以让我们每个元素都是字节,那我们的地址呢地址也需要对他进行强制类型转换,这样我们每当指向一个地址后进行+1指向下一个地址这样我的arr2数组就会被修改。
2.memmove
对于重叠的内存我们需要memove来处理
我们可以看memmove这个库函数的参数返回类型和memcpy是相同的
举个例子
#include <string.h>
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memmove(arr1+2, arr1, 5*sizeof(arr1[0]));
int i = 0;
for (i = 0; i < 10; i++)//打印
{
printf("%d ", arr1[i]);
}
return 0;
}
在这个例子中我们可以看到memmove可以对同一个数组来进行处理运行结果如下
我们所求的结果就是12123458910,但如果我们用memcpy进行相同的操作可能出现
这就是因为内存重叠的结果为什么会是这样呢
模拟实现memmove
void* My_memmove(void* dest, void* src, size_t count)
{
void* ret = dest;
if (dest < src)
{
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (count--)
{
*((char*)dest + count) = *((char*)src + count);
}
}
return ret;
}