模拟实现memmove(含GIF演示),清晰易懂

1.准备阶段

不同于strcpy的只针对于字符串进行拷贝,memcpy是针对于内存进行拷贝,可以对整形,长整型,结构体等类型进行拷贝,更加灵活通用。
但是由于我们不知道使用这个函数的用户会拷贝什么类型的数据,所以我们需要用void*指针来接收地址,然后根据传进来的num(也就是需要拷贝的总字节数),来进行一个字节一个字节的拷贝。

在这里插入图片描述观察一下这张图片↑
1.首先这个dest指针,就是我们传入的目标地址(拷贝到的地址)
2.这个src指针,就是即将被拷贝的地址
3.num表示要拷贝的总字节数

2.实现原理

①.正常情况

正常情况下,也就是内存不重叠的地方,实现起来并不困难,就是根据src的位置一个字节一个字节地往前覆盖,如下图
在这里插入图片描述

②.特殊情况

情况1

为了方便描述,我默认拷贝 3 个字节,并且默认将src为起始位置拷贝到dest中

在这里插入图片描述这种情况下,src>dest,并且有内存重叠的部分,按照我们的常规思路,就是类似于strcpy一样,根据src的位置依次往前拷贝,如下:
在这里插入图片描述

情况2

为了方便描述,我默认拷贝 3 个字节,并且默认将src为起始位置拷贝到dest中

但是呢,在某种特殊情况(即内存重叠)中,按照正常的拷贝逻辑就可能没法实现预想中的功能。

比如这种情况,src<dest,我们计划将src后面三个字节的内容拷贝到dest中,dest后面三个字节拷贝完成后本应该是:abc在这里插入图片描述
但实际上:

在这里插入图片描述原本计划dest开始的三个字节应该是abc,但是实际上却是aba,一开始的c就被直接覆盖了。
对于这种情况,我们应该反着拷贝,也就是这样:↓
在这里插入图片描述

规律总结:

根据正常情况和两个特殊情况,我们可以得出以下结论
1.如果src<dest(也就是src在dest左边的时候),那么我们就要从后往前覆盖
2.其他情况下,从前往后覆盖都可以成功拷贝

3.完整代码

void* myMemmove(void* dest,void* src, size_t num)  //这里的num表示的是拷贝的总字节数
{
	const char* ret = dest;  //记录dest的起始位置便于返回
	assert(dest && src);    //断言
	if (dest < src)         //情况1
	{
		while (num--)
		{
			*((char*)dest) = *((char*)src);  
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else                  //情况2
	{
		while (num--) //判断完真假后--
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;   //返回起始位置指针
}

部分代码细节

while (num--)
		{
			*((char*)dest) = *((char*)src);  
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}

正如文章开头所讲,我们不知道使用这个函数的用户将会传入什么类型的数据,所以用void接收后的覆盖过程,我们需要一个字节一个字节地覆盖,所以需要强转成char

其次,为了下一个字节的覆盖,dest和src都要强转成char*后再+1.

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

答辣喇叭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值