库函数memcpy,memmove的模拟实现

今天跟大家分享两个内存操作函数的底层逻辑和模拟实现:

由于strcpy(字符拷贝函数)只能拷贝字符的局限性,我们需要运用memcpy(内存拷贝函数)来实现更多数据类型的拷贝,memmove也是同理。

对于函数原型的研究,我们通常参考cplusplus网站(推荐使用右上角旧版)cplusplus.comicon-default.png?t=N7T8https://cplusplus.com/

首先是memcpy和memmove的原型:

void * memcpy ( void * destination, const void * source, size_t num );
void * memmove ( void * destination, const void * source, size_t num );

通过原型,我们可以看出对于未确定的数据类型,我们选择用void*类型的指针进行接收 并返回,这是mem类型函数的最基本原理(类似情况同理)。接下来用例子分析:

 int arr1[20] = { 0 };
 int arr2[20] = { 1,2,3,4,5,6,7,8,9 ,0};

 我们需要将arr2中的(int)整型数据(拷贝多少看具体需求)拷贝到arr1当中,具体操作:

void* my_memcpy(void* dest,const void* src,size_t num)
{
    assert(dest && src);//断言操作,确保程序健壮性(可参考cplusplus
   while (num--)
    {
        *(char*)dest = *(char*)src;

       dest = (char*)dest + 1;
       src = (char*)src + 1;
    }
}

 代码中有一个关键点--强制类型转换为char*类型,因为不确定我们具体要操作的数据类型是什么,所以我们只能一个字节一个字节地进行拷贝,那为什么不能是in类型或者其他类型呢?因为只有1个字节是最基础的,所有的数据类型都可以用char*(1个字节)的倍数来表示。剩下的就是最基本的数据传参,将arr2中的数据传入arr1中。
memmove可以看作是memcpy的一种特殊情况,
 

int arr1[20] = { 0 };
 int arr2[20] = { 1,2,3,4,5,6,7,8,9 ,0};

memmove是发生在同一块空间的拷贝,也就是自己对自己的拷贝,如图:

我们需要将3,4,5,6,7拷贝进1,2,3,4,5中,如果从后往前拷贝,也就是7->5,6->4时,出现了内存的重叠,这就是memcpy和memmove的区别所在 。但是dest(目标地址)和src(传入地址)一定是如上图的先后顺序吗?所以我们需要对dest和src的地址先后进行讨论:

void* my_memmove(void* dest, const void* src, size_t sz)
{
    if (dest < src)
    {
        //前->后
        while (sz--)
        {
            *(char*)dest = *(char*)src;
            dest = (char*)dest + 1;
            src = (char*)src + 1;
        }
    }
    else
    {
        //后->前
        while (sz--)
        {
            *((char*)dest + sz) = *((char*)src + sz);
        }
    }
}

 代码中有两个关键点--sz(拷贝字节数)和前后讨论

从前向后时,像memcpy一样依次拷贝;

从后向前时,

由于是一个字节一个字节从后向前拷贝,所以是从src+sz(个字节)开始向前拷贝。可以自己画图试试。

以上就是本期分享,

如有错误,敬请指正,谢谢大家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值