memmove的自我实现

1函数void* memmove(void* dest, void* sour, size_t num);可以将地址sour的拷贝给地址dest并且向后延申至num个字节。与函数memcpy有相同的作用,但是memmove可以处理的源内存块和⽬标内存块是重叠的情况,简单来说就是当处理对象是数组是memmove可以实现数组的自我拷贝。像:

由图中代码可以看出memmove实现了数组arr的自我拷贝。而memcpy就不可以(少数编译器可以)。在这里插入图片描述

memmove的实现:

下面是一段可以实现memcpy的代码,因两着很相似所以尝试使用。

void* my_memmove(void* arr2, void* arr, size_t bit)
{
	if(bit>0)
	{
		*(char*)arr2 = *(char*)arr;
		((char*)arr2)++;
		((char*)arr)++;
		bit--;
		my_memmove(arr2, arr, bit);
	}
	return (char*)arr2-1;
}

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

但使用这段代码来将蓝色部分变成红色部分时,在这里插入图片描述
我们期望的运行结果是”1 2 3 1 2 3 4 8 9 10“但实际是:在这里插入图片描述
经过画图我们可以看出这是从前向后排后面的数字被前面的覆盖掉了,所以我们采用从后向前赋值的方式。但是当这样写时,想要将红色化为蓝色部分时又会出现覆盖的问题,而这时我们就需要从前向后排。在这里插入图片描述

总结:

经过上面的分析可以得出:当要修改的地址大于源地址时我们需要从后向前排,而相反我们则需要从前向后排,注意当两者不存在交集时可以直接从后向前排、从后向前亦可。

所以对代码修正得:

void* my2_memmove(void* arr2, void* arr, size_t num)
{
	if (num > 0)
	{
		*(char*)arr2 = *(char*)arr;
		arr2 = (char*)arr2 - 1;
		arr = (char*)arr - 1;
		num--;
		my2_memmove(arr2, arr, num);
	}
	return (char*)arr2 - 1;
}

void* my_memmove(void* arr2, void* arr, size_t num)
{
	if (num > 0 && arr2 < arr)
	{
		*(char*)arr2 = *(char*)arr;
		arr2 = (char*)arr2 + 1;
		arr = (char*)arr + 1;
		num--;
		my_memmove(arr2, arr, num);
	}
	if (num >= 0 && arr2<arr)
	{
		return (char*)arr2 - 1;
	}
	arr = (char*)arr + num - 1;
	arr2 = (char*)arr2 + num - 1;
	return my2_memmove(arr2, arr, num);
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr, arr+3, 4 * sizeof(int));
	my_memmove(arr2 + 3, arr2, 4 * sizeof(int));
	int i = 0;
	printf("arr:");
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\narr2:");
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

由图我们得到了”1 2 3 1 2 3 4 8 9 0“这个运行结果。在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值