C语言内存函数-memmove(Move block of memory)使用和模拟实现

时间:2024-10-08 11:32:13

代码格式:

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

memmove使用要点:

1:和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的

2:如果源空间和目标空间出现重叠,就得使用memmove函数处理

代码示例:

#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1 + 2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

代码解析:
这里只有一个数组arr1,我们传入的地址为arr1+2和arr1,分别表示数组第三个元素的地址(&arr1[3]),和数组首元素的地址

在这里插入图片描述

memmove的模拟实现:

在实现之前我们先理解一下思路:
memmove的实现其实有一种比较简单的方法,就是我们只需要创造一个和arr一模一样的数组brr,由于是两个不同的数组,内存地址是不同的,只是数组元素是相同的,这样我们就解决重叠的问题了
在这里插入图片描述
但是我们能不能只通过arr自身而不去创造brr去实现memmove呢?
在这里插入图片描述
如图:我们需要将绿色方框中的元素拷贝到红色方框中的元素,可以像这样拷贝,我们先将a[4]=3拷贝到a[6]=5中,然后将a[3]=2拷贝到a[5]=4中…这样就可以避免重叠拷贝,造成拷贝元素不是我们想要的情况了

而如果我们需要将图中绿色方框中的元素拷贝到前面红色方框的元素呢?
在这里插入图片描述
其实方式都是一样的

综上如果我们只用数组arr而不创造数组brr的话,我们需要考虑到两种情况,一个是往前拷贝,一个是往后拷贝,所以针对情况我们就一定会用到if语句

具体实现代码如下:

void* my_memmove(void* dest, const void* src, size_t sz)
{
	assert(dest && src);
	void* ret = dest;//记录dest启始地址
	if (dest < src)//从前向后
	{
		for (int i = 0; i < sz; i++)
		{
			*(char*)dest = *(char*)src;
				dest = (char*)dest+1;
				src = (char*)src + 1;
		}
	}
	else//从后向前
	{
		while (sz--)
		{
			*((char*)dest + sz) = *((char*)src + sz);
		}
	}
	return ret;
}

代码解析:
* (char * )dest = * (char*)src是将dest和src强制转换为char*,方便后续可以一个字节一个字节的拷贝

dest = (char*)+1和src = (char*)src + 1是将两个数组都强转后向后移动一个字节

由于while(sz–)是先判断sz是否=0,判断完后再执行后置减减,然后在通过 *((char *)dest + sz) = * ((char * )src + sz)确定需要拷贝的数组和要拷贝数字的位置,我们用一个图来说明:

我们需要将绿色方框中的元素拷贝进红色方框中去,下面是各元素的16进制表示
在这里插入图片描述
在这里插入图片描述