内存函数memcpy和memmove详解及模拟实现

   前言:

                     大家好,我学习完memmove函数后做了如下一些总结,和大家一起探讨交流,如有错误和遗漏欢迎大家在评论区指出。

介绍memmove函数:

          君子性非异也,善假于物也。想要了解一个函数,首先可以利用工具,了解它的基本用法

这里我用www.cplusplus.com这个网站进行查找。

通过这个网站我们可以基本了解到这个函数的作用:

从*source一个字节一个字节的拷贝num个字节到*destination

区分memcpy和memmove:

       在学习memmove之前,我们可以先了解一下memcpy,同样通过上面的网站查找:

不难发现,这两个函数的差别好像不大

其实 标准值规定:

memcpy来实现不重叠的内存拷贝;

memmove来实现重叠的内存拷贝。

那么什么是重叠的内存拷贝呢?

int main()//内存里以字节为单位拷贝
{
	int arr1[] = { 1,2,3,4,5,6,7,8 };
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	memmove(arr1, arr1+2, 20);
	print(arr1, sz);
	return 0;
}

像我这样*source是arr1+2,*destination是arr1,拷贝20个字节,可以发现数组中3,4,5所占的字节重叠了,这就是重叠的内存。

模拟实现memcpy:

    由浅入深,我们先来模拟不重叠的内存拷贝也就是模拟memcpy:

先准备两个数组,写一个打印数组的函数:

#include<stdio.h>
void print(int arr[], int sz)//打印数组的函数
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main()//内存里以字节为单位拷贝
{
	int arr1[] = { 1,2,3,4,5,6,7,8 };
	int arr2[] = { 9,8,7,6,5 };
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	my_memcpy(arr1, arr2, 16);
	print(arr1, sz);
	return 0;
}

接下来就是拷贝过程的实现:

其实只要利用循环,将*destination = *source,再都加上1,循环num次,但要注意他们都是void*类型,想要一个字节一个字节的拷贝和进行加减操作的话,必须先把他们强制转换为char*类型

void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* arr3 = dest;
	while (num--)
	{
		*((char*)dest) = *((char*)src);
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return arr3;
}

最后整个代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void print(int arr[], int sz)//打印数组的函数
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* arr3 = dest;
	while (num--)
	{
		*((char*)dest) = *((char*)src);
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return arr3;
}
int main()//内存里以字节为单位拷贝
{
	int arr1[] = { 1,2,3,4,5,6,7,8 };
	int arr2[] = { 9,8,7,6,5 };
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	my_memcpy(arr1, arr2, 16);
	print(arr1, sz);
	return 0;
}

运行输出如下:

模拟实现memmove:

其实重叠部分的拷贝难点就在于:当进行到重叠部分的拷贝时,可能原始数据已被修改,导致拷贝出错,最简单的解决办法就是将原始数据再放入一块空间记住下来,但是这样就又多占了一块内存,有没有其他更高效的方法呢?

很简单可以分两种情况:

1.*destination在*source前面:

这个时候我们像memcpy一样拷贝可以拷贝完成。

2.*destination在*source后面:

这时候再从前往后拷贝,就会把修改过的数据再次拷贝一份。

解决方法就是不妨试试从后往前拷贝,这样就可以完成,所以最后函数内部代码如下:

void* my_memmove(void* dest, const void* src, size_t num)
{
	void* arr3 = dest;
	assert(dest && src);
	if (dest < src)//从前往后拷贝
	{
		while (num--)
		{
			*((char*)dest) = *((char*)src);
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else if (dest > src)//从后往前拷贝
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}

	return arr3;
}

最后整个代码如下:

#include <stdio.h>
#include<assert.h>
void print(int arr[], int sz)//打印数组的函数
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
void* my_memmove(void* dest, const void* src, size_t num)
{
	void* arr3 = dest;
	assert(dest && src);
	if (dest < src)//从前往后拷贝
	{
		while (num--)
		{
			*((char*)dest) = *((char*)src);
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else if (dest > src)//从后往前拷贝
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}

	return arr3;
}
int main()//内存里以字节为单位拷贝
{
	int arr1[] = { 1,2,3,4,5,6,7,8 };
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	my_memmove(arr1, arr1+2, 20);
	print(arr1, sz);
	return 0;
}

运行输出如下:

最后拷贝成功。

大家有什么建议或者补充欢迎大家留在评论区,谢谢大家。

  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

咬_咬

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

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

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

打赏作者

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

抵扣说明:

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

余额充值