内存函数 memcpy、memmove 的简单模拟实现

一、memcpy 函数

数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。注意是以字节为单位进行拷贝。函数声明如下:

1、参数返回值解析

第二个参数 src:源地址,即你要从哪开始拷贝。

第三个参数 count:字节数,即从源地址起始位置开始一共要拷贝多少个字节。

第一个参数 dst:目的地址。也就是你拷贝的内容要放到哪。

返回值:返回目标空间的地址。

2、使用注意

该函数有如下两个注意事项:

  • 因为是内存函数,并不会以' \0 '作为结束符。
  • 不适合用于处理内存重叠的情况。举个例子,将源地址的第1 ~ 4个字节拷贝到源地址的第3 ~ 6的字节位置上,此时发生了内存重叠。(如果有内存重叠,则需要使用memmove函数)

3、模拟实现

因为是逐字节拷贝,所以解引用的时候,每次访问只能访问一个字节,前面在说指针类型的时候提到,指针类型决定了解引用每次可以访问多少个字节。

因此,在拷贝之前,先将源地址和目标地址的指针类型转化为 char* 类型,这样的话,每次解引用就只会访问一个字节。

#include <assert.h>
#include <stdio.h>

void* my_memcpy(void* dst, const void* src, size_t num)
{
	assert(dst && src);

	char* target = (char*)dst;		        // 转化为 char*,解引用时只会访问一个字节		
	const char* source = (const char*)src;  

	while (num--)
	{
		*target = *source;
		target++;
		source++;
	}
	return dst;
}

int main() {
	int dst[10] = { 0 };
	int src[5] = { 1,2,3,4,5 };

	my_memcpy(dst, src, sizeof(src));

	for (size_t i = 0; i < 10; i++)
	{
		printf("%d ", dst[i]);
	}
	return 0;
}

测试结果如下:

二、memmove 函数

1、认识memmove函数

当源地址和目标地址没有重叠的时候,memmove函数 和 memcpy函数的功能是一样的,但是如果遇到内存重叠的情况,比如将源地址的第1 ~ 4个字节拷贝到源地址的第3 ~ 6的字节位置上。

函数声明如下, 参数解析可以参考 memcpy 函数

 

2、memmove函数模拟实现

在模拟实现的时候,需要考虑的是,源地址和目的地址的位置。如果源地址在目的地址的左边,此时应该先将末尾的字节拷贝到目标地址的末尾。如果按正常顺序拷贝的话,就会变成右边这种情况,明明 3 也是要拷贝到目标地址的,但是现在却被新拷贝的覆盖了。

如果        边,应该是从后往前拷贝。这个时候相当于是把蓝色框里的内容向后移动了一样,最先移动的是最右边的内容。

 如果源地址在目的地址的右边,那么这个时候,就应该是从前往后拷贝。这个时候就相当于是把蓝色框里的内容向前移动了一样,最先移动的是最左边的内容。

void* my_memmove(void* dst, const void* src, size_t num)
{
	assert(dst && src);

	char* target = (char*)dst;
	const char* source = (const char*)src;


	if (src < dst)
	{
		// 源地址在目的地址的左边
		while (num--)
		{
			*(target + num) = *(source + num);
		}
	}
	else if (src > dst)
	{
		// 源地址在目的地址的右边
		while (num--)
		{
			*target = *source;
			target++;
			source++;
		}
	}
	else
	{
		// 无需拷贝,直接返回
		return (void*)src;
	}
}

int main() {
	int arr[8] = { 1,2,3,4,5,6,7,8 };

	my_memmove(arr, arr + 2 , 4 * sizeof(int));		//移动4个元素(16个字节)

	for (size_t i = 0; i < 8; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 测试结果为:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值