【C语言】memmove()函数(拷贝重叠内存块函数详解)

这篇具有很好参考价值的文章主要介绍了【C语言】memmove()函数(拷贝重叠内存块函数详解)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🦄个人主页:修修修也

🎏所属专栏:C语言

⚙️操作环境:Visual Studio 2022

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++


目录

 一.memmove()函数简介

1.函数功能

2.函数参数

1>.void * destination

2>.onst void * source

3>.size_t num

3.函数返回值

4.函数头文件

二.memmove()函数的具体使用

1.使用memmove()函数完成拷贝整型数组数据(目的地与源重叠)

2.使用memmove()函数完成拷贝字符数组数据(目的地与源重叠)

三.模拟实现memmove()函数功能

🎏实现思路

1.函数参数及返回值设定逻辑

📌函数参数:

📌函数返回值:

2.函数功能实现逻辑

1.情况一(两个内存块不重叠)

2.情况二(两个内存块有重叠)

🎏代码编写

🎏运行测试

1.测试my_memmove()函数的逆序拷贝

2.测试my_memmove()函数的顺序拷贝

结语


 一.memmove()函数简介

我们先来看一下cplusplus.com - The C++ Resources Network网站上memmove()函数基本信息

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

1.函数功能

可以看到,memmove()函数的功能是:

源头指向的内存块拷贝固定字节数的数据目标指向的内存块,并且源头的内存块与目标内存块可以重叠.(最后一点是memmove()与memcpy最大的区别)


2.函数参数

该函数一共有三个参数,分别是:

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

1>.void * destination

第一个参数的类型是无类型指针(void*),它指向拷贝的目的地内存块,它的作用是为函数提供目的地的内存块起始地址,以便函数能够准确地将内容拷贝到我们需要的内存空间.

2>.onst void * source

第二个参数的类型是被const修饰(const修饰的指针,const在*左边表示指针指向的内容不可修改,const在*右边表示指针的指向不可修改)无类型指针(void*),它指向拷贝数据的来源内存块,它的作用是为函数提供拷贝源头内存块起始地址,以便函数能够准确找到拷贝的源头进行拷贝.

3>.size_t num

第三个参数的类型是size_t(无符号整形),它表示要拷贝数据的字节数,它的作用是告诉函数需要拷贝的字节数是多少,以便函数精准的拷贝该数目字节数空间的内容到目的地.


3.函数返回值

函数的返回值类型是无类型指针(void*),它的作用是在函数运行结束后返回拷贝后的目的地内存块的起始地址.


4.函数头文件

该函数包含在头文件<string.h>中.


二.memmove()函数的具体使用

memmove()函数的使用场景是:

当我们想拷贝一个整型数组/结构体/枚举常量等strcpy()函数无法拷贝的数据,并且目的地内存块和源头内存块可能会有重叠的时候,我们可以考虑使用memmove()函数来完实现这一诉求,当然,想要使用memmove()函数拷贝字符串数据或者拷贝目的地内存块和源头内存块不重叠也是可以的.(但是会有些杀鸡用牛刀的感觉哈哈哈)

下面是拷贝时源内存块与目标内存块重叠的情况示意图:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

1.使用memmove()函数完成拷贝整型数组数据(目的地与源重叠)

因为拷贝目的地内存块与源内存块不重叠的情况我们已经在memcpy()函数部分详细展示过了,因此在memmove()函数部分我们将着重展示它的内存块重叠时的使用情况.

如下,我们使用memmove()函数将arr数组中的1,2,3,4,5拷贝到3,4,5,6,7的位置上去:

分别给memmove()函数传入三个参数:

拷贝目的地地址(即arr+2),拷贝来源地址(即arr),拷贝字节数(即sizeof(arr[0])*5).

/* memmove 使用测试 */
#include <stdio.h>
#include <string.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr+2, arr, sizeof(arr[0])*5);		
	//sizeof(arr[0])计算的结果是arr数组中一个元素的字节大小,乘5代表5个
	
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

在vs编译器中运行查看结果:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

可以看到memmove()函数成功的将arr数组中的1,2,3,4,5拷贝到了3,4,5,6,7的位置上.


2.使用memmove()函数完成拷贝字符数组数据(目的地与源重叠)

如下,我们使用memmove()函数将str数组的" very useful"拷贝到" useful......"的位置上去:

分别给memmove()函数传入三个参数:

拷贝目的地地址(即str+20),拷贝来源地址(即str+15),拷贝字节数(即11).

/* memmove 使用测试 */
#include <stdio.h>
#include <string.h>

int main()
{
	char str[] = "memmove can be very useful......";
	memmove(str + 20, str + 15, 11);
	//使用memmove()函数拷贝内存块重叠字符串

	printf("%s\n", str);
	return 0;
}

在vs编译器中运行查看结果:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

 可以看到memmove()函数成功的将str数组的" very useful"拷贝到了" useful......"的位置上.


三.模拟实现memmove()函数功能

🎏实现思路

1.函数参数及返回值设定逻辑

📌函数参数:
void * destination

因为memmove()函数要实现的是内存空间的拷贝,所以在使用memmove()函数时我们难免会遇到拷贝不同类型数据的可能,因此在这里我们需要将目的地的地址类型设置为无类型指针(void*),以便函数后续可以处理任意类型的数据.

const void * source

来源地址的类型设置为无类型指针(void*)的原因与目的地的原因相同,都是便于函数可以处理任意类型的数据.

而给来源的地址指针加上const的原因是防止拷贝的过程中将来源的内容不慎修改,在*指针左侧加上const就可以使const修饰的指针指向的内容变成常量.

size_t num

 因为要拷贝的字节数恒为非负数,因此字节数的类型是无符号整形(size_t).

📌函数返回值:
void*

函数返回值设置为void*的原因同目的地及来源地相同,都是便于函数可以在处理完任意类型的数据后可以返回目的地的地址.


2.函数功能实现逻辑

在讲实现逻辑之前,我们先分情况讨论一下在拷贝数据时,我们可能遇到的几种情况:

注:以下演示中,*src指针指向源头起始内存块,*dest指针指向目标起始内存块.

1.情况一(两个内存块不重叠)

这种情况下内存空间的拷贝逻辑是较为简单的,不论是数据从前向后拷贝还是从后向前拷贝,结果都是正确的.

例如这种情况:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

 或是这种情况:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++


2.情况二(两个内存块有重叠)

这种情况就比较复杂了,同样分两种情况,如图:

源头指针在前时,只能从源头内存块的后端向前端移动拷贝:

 【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

拷贝逻辑示意图(序号代表拷贝次序):

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

目的地指针在前时,只能从源头内存块的前端向后端移动拷贝:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

拷贝逻辑示意图(序号代表拷贝次序):

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

分析清楚上面四种不同的情况,我们就可以在代码的编写中对不同情况进行分情况讨论了.

当然这里的分情况是十分灵活的,你可以四种情况各分一种,也可以按拷贝模式来分,从前向后拷的算一种,从后向前拷的算另一种.

除了两个必须按固定方式拷贝的情况之外,剩下两种情况无论按哪种方式拷贝都行.

那么我们在这里就选择一种最简单也最容易理解的方式来模拟实现memmove()函数吧.

如果源头指针在前(小),从后向前拷贝;目的地指针在前(小),从前向后拷贝

数据在内存中的存储示意图:

 【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++


🎏代码编写

清楚了不同情况的拷贝逻辑后,代码的编写就只需要按上面说的分两种情况就好了,以及,函数在实现时的其他需要注意的点我都标注在注释中了.

综上,my_memmove()函数的完整实现代码如下:

//模拟实现my_memmove()函数

void* my_memmove(void* destination, const void* source, size_t num)
{
	assert(destination);        //防止源头或目的地指针为NULL
	assert(source);
	void* ret = destination;
	if (source < destination)   //内存中数据的存储是由低地址到高地址的
	{
		//从后向前拷贝
		while (num--)   //以num为20为例,在num进入while循环之后,就立刻--,变成19了
		{
			*((char*)destination + num ) = *((char*)source + num );
			//这时source+num刚好指向的是源头内存块的最后一个字节
		}
	}
	else
	{
		while (num--)
		{
			//从前向后拷贝
			*((char*)destination) = *((char*)source);
			++((char*)destination);        
			++((char*)source);
			//这里使用后置++的话一定要给(char*)destination整体带上括号
			//否则后置++的优先级比(char*)的强制类型转换的优先级高,
			//导致指针类型还是void*时就进行++操作,这是在C标准中是不允许的
		}
	}
	return ret;
}

🎏运行测试

1.测试my_memmove()函数的逆序拷贝

如下,我们使用my_memmove()函数将arr数组的1,2,3,4,5拷贝到3,4,5,6,7的位置上:

即按照前面提到的这种情况进行拷贝:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

vs2022测试运行结果:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

可以看到my_memmove()函数成功的将arr数组中的1,2,3,4,5拷贝到了3,4,5,6,7的位置上.


2.测试my_memmove()函数的顺序拷贝

如下,我们使用my_memmove()函数将arr数组的3,4,5,6,7拷贝到1,2,3,4,5的位置上:

即按照前面提到的这种情况拷贝:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

vs2022中测试运行结果:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

可以看到my_memmove()函数成功的将arr数组中的3,4,5,6,7拷贝到了1,2,3,4,5的位置上.


结语

希望这篇memmove()函数的介绍到能对大家有所帮助,欢迎大佬们留言或私信与我交流.

最后的最后,感谢这位大佬指出了我在memcpy()函数阶段模拟实现的不足,因为和他的交流,才促成了这篇博客的产生:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

相关文章推荐

【C语言】memcpy()函数

【C语言】memset()函数

【C语言】strcpy()函数

【C语言】strlen()函数

【C语言】rand()函数(如何生成指定范围随机数)

【实用调试技巧】总是找不到Bug?手把手教你在vs2022中调试程序


【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++


C语言内存相关库函数思维导图:

【C语言】memmove()函数(拷贝重叠内存块函数详解),C语言,c语言,开发语言,学习,笔记,c++文章来源地址https://www.toymoban.com/news/detail-738446.html

到了这里,关于【C语言】memmove()函数(拷贝重叠内存块函数详解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言内存函数精选】memcpy、memset、memmove及仿真实现!掌握内存操作的艺术!

    ❤️ 博客主页: 小镇敲码人 🍏 欢迎关注:👍点赞 👂🏽留言 😍收藏 🌞 任尔江湖满血骨,我自踏雪寻梅香。 万千浮云遮碧月,独傲天下百坚强。 男儿应有龙腾志,盖世一意转洪荒。 莫使此生无痕度,终归人间一捧黄。🍎🍎🍎 ❤️ 我的努力求学没有得到别的好处,只

    2024年02月15日
    浏览(27)
  • 来不及哀悼了,接下来上场的是C语言内存函数memcpy,memmove,memset,memcmp

    今天又来写一篇C的文章,这里要讲的是C语言中的几个内存函数,主要是讲解功能和用法,望能耐心观看哦。望官方也多多曝光。 目录 memcpy  memmove memset  memcmp  memcpy  是 C 语言标准库中的一个函数,用于复制内存块的内容。它的主要作用是将一个源内存区域的内容复制到

    2024年02月22日
    浏览(29)
  • 【C语言】memcpy,memmove,memcmp,memset函数详解

    💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃 个人主页 :阿然成长日记 👈点击可跳转 📆 个人专栏: 🔹数据结构与算法🔹C语言进阶 🚩 不能则学,不知则问,耻于问人,决无长进 🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍 #includestring.h 与strn

    2024年02月17日
    浏览(23)
  • C语言内存操作函数,memcpy的使用和模拟实现,memmove的使用和模拟实现,memcmp的使用,memset的使用。

    函数原型: void *dest 目标数据首元素地址 const void *src 源数据(需要拷贝过去的数据) size_t count 需要拷贝数据的字节大小 void *memcpy 拷贝结束后,返回目标数据的起始地址 函数作用: 拷贝 count 个字节的数据从源数据起始地址到目标空间。 函数的使用 函数的模拟实现: 注:

    2024年02月09日
    浏览(37)
  • 【C语言】memcpy()函数(内存块拷贝函数)

    🦄 个人主页 :修修修也 🎏 所属专栏 :C语言 ⚙️ 操作环境 : Visual Studio 2022 目录 一.memcpy()函数简介 🎏函数功能 🎏函数参数 📌void * destination 📌const void * source 📌size_t num 🎏函数返回值 🎏函数头文件 二.memcpy()函数的具体使用 🎏使用memcpy()函数完成拷贝整型数组数据 🎏使

    2024年02月05日
    浏览(28)
  • 【c++中内存拷贝函数(C++ memcpy)详解】

    原型 :void*memcpy(void*dest, const void*src,unsigned int count);  功能 :由src所指内存区域复制count个字节到dest所指内存区域。   说明 :src和dest所指内存区域不能重叠,函数返回指向dest的指针。     举例 :  下面自行实现这个函数 程序清单 1 V0.1版程序  程序清单 2 测试V0.1用例   

    2023年04月20日
    浏览(24)
  • 【C语言】strcpy()函数(字符串拷贝函数详解)

    🦄 个人主页 :修修修也 🎏 所属专栏 :C语言 ⚙️ 操作环境 : Visual Studio 2022 目录  一.strcpy()函数简介 1.函数功能 2.函数参数 1.char * destination 2.const char * source 3.函数返回值 4.函数头文件 二.strcpy()函数的具体使用 1.使用strcpy()函数完成字符数组间的字符拷贝 2.使用strcpy()函数完成

    2024年02月03日
    浏览(34)
  • C语言-内存函数详解

    返回类型和参数: 1.函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 2.这个函数在遇到 ‘\\0’ 的时候并不会停下来。 3. 如果source和destination有任何的重叠,复制的结果都是未定义的。 4.注意单位是字节 5.头文件:#includestring.h memcpy使用: 运行

    2024年02月05日
    浏览(27)
  • C语言-详解内存函数

    它的函数原型如下: 具体的函数介绍如下: 好,相信同学们看了这个函数,应该是能够简单了解函数中各个参数的用法。 下面我们来总结一下: 函数 memcpy 从 source 的位置开始向后复制 num 个字节的数据到 destination 指向的内存位置。 这个函数在遇到 \\\'\\0\\\' 的时候并不会停下来。

    2024年04月16日
    浏览(42)
  • C语言内存函数详解

    本章内容主要讲解:memcpy(内存拷贝函数),memmove(内存移动函数),memcmp(内存比较函数)的 基本作用 和 模拟实现 。 1.memcpy函数 函数功能:从source指向的内存空间处拷贝num个字节的内容到destination指向的内存中, 当拷贝的内容是 \\\'\\0\\\' 时,函数不会主动停下来,除非拷贝的内容达

    2024年02月14日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包