理解memcpy
在cplusplus中对该函数的解释见下图
我们可以看出该函数有三个参数:1.destiation 为需要被覆盖目标的地址,2.source为需要复制的内容的地址,3.num为需要复制的字节数。
下面我们以 int 数组为例
下图中 arr1为目标地址,arr2为需要复制的内容
当我们需要将arr2[ 1 ]的内容复制到arr1[ 1 ]时,首先我们需要 arr1[ 1 ]和 arr2[ 1 ] 的地址。我们知道 int 类型参数的大小为 4 字节并且我们需要复制的元素只有一个,所以 num 的值为 4 。故函数应该这样写:memcpy(arr1, arr2, 4)
int main()
{
int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr2[5] = { 101, 102, 103, 104, 105 };
memcpy(arr1, arr2, 4);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
执行后arr1与arr2的内容如下图
我们再以 char 类型为例
我们创建两个字符数组 str1 与 str2
我们如果需要将"wxyz" 覆盖 "defg",需要找到 字符 'd' 的地址和字符 'w' 的地址即可。字符'd'的地址为 str1 + 3, w为str2首元素所以直接写str2即可,因为 char 类型的大小为 1 字节,我们需要复制的元素个数为 4 个 ,所以 num 的值也只能为 4 ,所以函数的写法为:
memcpy(str1+3, str2, 4)
int main()
{
char str1[10] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\0' };
char str2[5] = { 'w', 'x', 'y', 'z', '\0' };
memcpy(str1 + 3, str2, 4);
for (int i = 0; i < 10; i++)
{
printf("%c ", str1[i]);
}
return 0;
}
从中我们不难看出,memcpy函数所操作的是内存本身,与数据的类型(int,char,float)无关。
函数只将 目标内容 与 需要复制的内容一一替换。最后再将其转换成所需要的类型就达成目的了。
所以 num 的值需要自行计算,且其公式为
num =(元素类型的大小 * 需要复制的元素个数)
模拟实现
分析
1.因为我们是模拟函数实现,所以我们创建的函数所需要的参数应该与被模拟函数一样。
2.根据函数工作原理,我们可以推测出,函数只将内存中的内容覆盖,并未做其他修改,所以我们只需将(void*)转换成 (char*)类型解引用后赋值即可达到一次目的。
3.因为每次只操作一个字节,所以需要进行 num 次循环。
所以最终代码为:
#include <assert.h>
void my_memcpy(void* str1, const void* str2, size_t sz)
{
while (sz)
{
assert(str1 && str2);
*(char*)str1 = *(char*)str2; //转换成(char*)再解引用即每次访问一个字节以达到内容一一对应的目的,且由于是函数接收的是void*类型无法直接解引用
((char*)str1)++; //((char*)str1)++与(char*)str1++存在符号优先级的问题,我们应该先转换成(char*)类型在++
((char*)str2)++;
sz--;
}
}
思考
该函数能否用于地址存在重复的情况 如 arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },我们将4,5,6,7,8复制到5,6,7,8,9中?或者将5,6,7,8,9复制到4,5,6,7,8?
答案是前者不行后者可以,对此有兴趣的老铁请关注笔者的后续内容~~