memcpy和memmove的模拟实现

        大家好,这篇文章主要是为大家做一些两个函数的模拟实现,在开始之前若不认识这两个函数可以去cplusplus了解一下再来继续阅读本篇文章。

        首先我们写一个平平无奇的主函数

int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	int brr[20] = { 0 };
	my_momcpy(brr, arr, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d", brr[i]);
	}
	return 0;
}

        在我们写函数之前,看图

因为这个函数实现的是对所有类型的copy操作

所以我们在不确定是那种类型数据是可以使用void*来实现

void my_momcpy(void* a, void* b, size_t n)

 已知a目的地,b源头,c要复制的地址大小

那么首先排除a,b为空的情况

	assert(a);
	assert(b);

那么我们现在需要处理的就是怎么把b里面的内容放到a里面

ab都是void*类型的直接进行赋值操作是不被允许的

那么就可以对他进行强制转换,那我们如何结束呢?

我们可以看见还有一个参数n他代表着要复制过去地址大小

那么综合起来

	while (n--)
	{
		*(char*)a = *(char*)b;
    }

 我们再加一点点点缀让他后移

	while (n--)
	{
		*(char*)a = *(char*)b;
		a = (char*)a + 1;
		b = (char*)b + 1;
	}

将a强制转换为char*类型加一使它指向后面的地址

现在我们来运行试一下

可以看见这就是我们想要的结果

但是细心一点你可能发现了,我们的函数与原版还差了一笔

 函数类型是void*,而我所写的类型是void

那么让我们稍作修改

void* my_momcpy(void* a, void* b, size_t n)
{
	void* c = a;
	assert(a);
	assert(b);
	while (n--)
	{
		*(char*)a = *(char*)b;
		a = (char*)a + 1;
		b = (char*)b + 1;
	}
	return c;
}

memcpy就已经写完了

下面让我们再来看memmove

其实两个函数的不同就在于memmove是在可能重叠的位置进行复制

那么我们就需要考虑两个空间前后的问题

第一种情况,目的地在源除之前,那么如果我们从前往后复制的话,没有很大的问题,但是我们并不确定那个在前面那个在后面,所以如果要从前到后复制就需要加上一个判断条件才能进行操作

	if (a < b)
	{
		while (n--)
		{
			*(char*)a = *(char*)b;
			a = (char*)a + 1;
			b = (char*)b + 1;
		}
	}

这样在我们确定的情况下我们才能进行从前到后的操作

第二种情况就是,目的地在源地之后,如果我们此时进行了从前往后的操作,那么图中4,5两个数字就会被覆盖出现问题,这就是为什么上一种情况加上一个判断的原因,既然已经判断过,那么从后向前的代码就比较简单了

    while (n--)
		{
			*((char*)a + n) = *((char*)b + n);
		}

第三种情况就是源地址与目的地没有接触,那么前后操作就没有什么区别了

下面让我们看看全部的代码

void* my_momove(void* a, void* b, size_t n)
{
	void* c = a;
	assert(a);
	assert(b);
	if (a < b)
	{
		while (n--)
		{
			*(char*)a = *(char*)b;
			a = (char*)a + 1;
			b = (char*)b + 1;
		}
	}
	else
	{
		while (n--)
		{
			*((char*)a + n) = *((char*)b + n);
		}
	}
	return c;
}

int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	my_momove(arr+2, arr, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d", arr[i]);
	}
	return 0;
}

 

我们如期得到了自己想要的结果

        好了本篇文章到这里就结束了,谢谢大家的支持,如果文章内容有所不对欢迎大家指出改正。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值