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

1.函数memcpy

c 复制代码
void * memcpy ( void * destination, const void * source, size_t num );

函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。

这个函数在遇到 '\0' 的时候并不会停下来。

如果source和destination有任何的重叠,复制的结果都是未定义的。所以这个函数只能拷贝两块不重叠空间的数据。

我们可以自己模仿实现一下,但是还需要注意几点,它的参数类型是void*,void* 类型的数据不能直接进行解引用操作,所以我们必须将它强制类型转换为其他类型,为了很好地应对所有类型的数据,我们可以将它强转成char*类型,这样一次只访问一个字节,更加细致。

c 复制代码
void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;//记录dest的起始位置
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;//因为强转只是临时的效果,所以
		src = (char*)src + 1;//需要写成这种形式来让dest和src
	}                        //后移
	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,0 };
	int arr2[20] = { 0 };
	my_memcpy(arr2, arr1, 40);
	int i = 0;
	for (i = 0; i < 20; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

2.函数memmove

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

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

举个例子,比如整型数组arr[]={1,2,3,4,5,6,7,8,9,10}

现在需要把1 2 3 4 5拷贝到3 4 5 6 7的位置,也就是dest>src(相较于低地址和高地址),那这个时候目标地址的范围和源地址的范围应该是这样:

如果我们需要自己实现这个函数,那就要搞清楚它是怎么拷贝的,比如它是从前向后拷贝。

所以我们只能改变策略,从后向前拷贝,这里说的前后是源地址src的前后,因为是从源地址拷到目标地址。

这是一种情况,我们还要考虑另一种情况,如果需要把3 4 5 6 7拷贝到1 2 3 4 5的位置,也就是dest>src,那这种情况我们需要将数据从前向后拷贝:

这样我们在模拟实现这个代码的时候,就要考虑两种情况:

c 复制代码
自己实现函数memmove  拷贝重叠空间的数据
//void * memmove ( void * destination, const void * source, size_t num );
void* my_memmove(void* dest, const void* src, size_t num)
{
	//分两种情况拷贝
	if (dest < src)
	{
		//从前向后拷贝
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//从后向前拷贝
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr + 2, arr, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

此次的分享到此为止,看到的小伙伴希望对您有帮助哦。

相关推荐
CodeCraft Studio29 分钟前
PPT处理控件Aspose.Slides教程:在 C# 中将 PPTX 转换为 Markdown
开发语言·c#·powerpoint·markdown·ppt·aspose·ai大模型
萧鼎1 小时前
深入理解 Python Scapy 库:网络安全与协议分析的瑞士军刀
开发语言·python·web安全
阿拉丁的梦4 小时前
教程1:用vscode->ptvsd-创建和调试一个UI(python)-转载官方翻译(有修正)
开发语言·python
木宇(记得热爱生活)4 小时前
一键搭建开发环境:制作bash shell脚本
开发语言·bash
Cisyam^4 小时前
Go环境搭建实战:告别Java环境配置的复杂
java·开发语言·golang
IAR Systems5 小时前
在IAR Embedded Workbench for Arm中实现Infineon TRAVEO™ T2G安全调试
开发语言·arm开发·安全·嵌入式软件开发·iar
jayzhang_5 小时前
SPARK入门
大数据·开发语言
蹦极的考拉5 小时前
网站日志里面老是出现{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22.....
android·开发语言·php
fured6 小时前
[调试][实现][原理]用Golang实现建议断点调试器
开发语言·后端·golang
大翻哥哥6 小时前
Python地理空间数据分析:从地图绘制到智能城市应用
开发语言·python·数据分析