目录
我相信大家在打开这篇博客之前一定都大致了解memcpy的的功能和函数原型了吧,
如果你还不太了解它的具体细节,不妨看一下这篇博客:memcpy函数详解
函数基本介绍
我们在实现memcpy库函数之前,我们不妨回忆一下memcpy都有几个参数,都是什么类型,函数返回值是什么?
void *memcpy( void *dest, const void *src, size_t count );
如上,memcpy有三个参数
第一个参数是void*类型的,是目的空间地址。
第二个也是void*类型的,是要拷贝内容空间地址。
第三个是size_t类型的(也就是无符号整型),是考拷贝内容的字节数。
返回值是一个指针类型为void*,是目标地址的起始空间
大致内容都了解完了,接下来就是该实现该函数了
模拟函数具体实现步骤
1、第一步给模拟函数起名
在模拟函数之前我们要先给我们的函数起个好听的名字,就叫my_memcpy吧(我的memcpy)
然后把目标空间地址、要拷贝内容空间地址、字节数传入进去
2、第二步写模拟函数主体
这一步我们要模仿着memcpy函数原型,来写我们的模拟函数
3、实现具体功能
memcpy函数的功能是把内存块拷贝到目标空间,但是问题来了,memcpy第三个参数是字节数,不是要拷贝数据的个数,这我们要怎么办呢?
接下来我将用下面的例子讲解实现的具体细节
上面要arr1中前5个数传递给arr2,共20个字节,我把他们在计算机中存储方式大致展示出来(以16进制存储)
(注:vs中是小端存储所以小端在前面,具体细节可查看:大小端字节序详解)
一般我们用地址赋值都会先把地址解引用并赋值,然后让地址++。
*dest = *src;
dest++;
src++;
可是,在模拟函数中,传参的地址都是void*类型的,当我们让地址++,地址不知道要跳几个字节。
比如:char* 类型的指针++,向后跳1个字节。int* 类型的指针++,向后跳4个字节
现在我们面临两个问题
1.指针类型为void*,无法++
2.要拷贝内容的个数不知道,通俗点就是我们不知道要拷贝几次或者两个指针要++几次
对于第一个问题,我们把指针强制类型转换,这样就可以++了。但是如果让指针类型转换成int*话,我们就要循环count/sizeof(int)次,这样太麻烦我们还带确定用户要拷贝内容的类型。
对于这个问题我们可以把指针类型转换成char* ,因为char*类型指针++向后跳一个字节(一个字节一个字节访问),不管是什么类型我们都可以一个一个字节的拷贝,这样我们也容易确定循环次数,为count。
同时我们也不要忘了,要拷贝一下目标地址的起始位置,因为函数要返回目标空间起始地址
void* my_memcpy(void* dest, const void* src, size_t count)
{
void* ret = dest;
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
最后为了函数的健壮性,避免用户传递空指针,我们可以用assert判断一下dest和src的是否为空指针(在使用assert()函数时,别忘了引用头文件#include<assert.h>)
assert(dest && src);
代码实现
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t count)
{
assert(dest && src);
void* ret = dest;
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[5] = { 0 };
my_memcpy(arr2, arr1, 20);
return 0;
}