admin管理员组

文章数量:1794759

打开C语言常用的内存函数大门(二)—— memmove()函数 (内含memmove的讲解和模拟实现)

1. 前言

在之前,我向大家介绍了C语言中的一个常用的内存函数memcpy函数。如果你还没看的话,建议你先去看memcpy函数这篇文章,因为接下来,可能会用到那篇文章的知识甚至会拓展没有讲过的知识。强烈建议先去看把一篇文章,文章链接:memcpy函数讲解及其模拟实现(点此查看即可)

那么在本文中,我将介绍继续介绍C语言中常用的内存函数——memmove()函数。

2. memmove()函数

memmove()函数的作用:将源空间的内容移动到目标空间上,也可以理解为将指定源空间的内容拷贝到目标空间中。

可能看到这里有的读者就会提出这么一个问题:

这不是跟memcpy()函数的功能一样吗?这是不一样的,可不敢将两者给弄混了。

2.1 memmove()函数与memcpy()函数的差异

在我们用memcpy函数时,不知道大家有没有想过这么一个问题:

代码语言:javascript代码运行次数:0运行复制
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };

	memcpy(arr1+3,arr1,12); //用memcpy拷贝自身的数据给自身

	for (int i = 0; i < 10; i++)
	{
		printf("%d ",arr1[i]);
	}

	return 0;
}

在VS上面你可能会成功运行这段代码,但这并不意味着这段代码是不存在问题的。你若是换一个别的编译器,可能上面的代码就跑不起来了。为什么会这样呢?

事实上,这种行为在memcpy函数看来是属于未定义的行为(想要操作的同一个对象里的俩成员之间出现了内存交织的情况)。你不妨想一下,你对一个未定义的行为进行了操作,这不就属于脱离了编译器的掌控,这种行为是十分危险的。编译器要的是稳稳的幸福。

那既然不能这么做,那有没有别的办法?

答案是有的,就是本文的主角—— memmove函数。

这也正是导致memmove函数与memcpy函数的差异所在: memmove函数能够处理同一个对象里的俩成员间内存空间出现交织的情况,而这正是memcpy函数所做不到的

可能读者们听到这里还是有点懵逼,到底什么情况下会出现内存交织的情况?

下面我将给出一副图,看完这幅图你也许就会懂了:

图解

结合着要求看,不难发现,元素4即是拷贝内容也是待拷贝内容的区域。不妨想一下,如果我们按照memcpy函数的方式进行内存操作时,那么元素1就会覆盖元素4的值,那么4这个数据就消失了。这个不是我们想看到的。因此,这也就是为什么memcpy函数处理不了内存空间有交织的数据的本质原因。

相信看完上述的解释后,你已经对memmove在什么情况下使用已经有大概的印象了。

那么接下来,我们就一起来探讨一下memmove函数如何使用?

2.2 memmove()函数的原型

memmove函数原型
代码语言:javascript代码运行次数:0运行复制
void * memmove ( void * destination, const void * source, size_t num );

这个跟memcpy的参数意思是一样的。为了提高读者们的学习效率,这里我就再写一遍:

返回值和形参

作用

返回值类型:void*

返回目的地空间的地址。(说大白话,就是返回你想要拷贝内容到那个空间的地址,不过我们很少会用到它的返回值)

destination

一个空指针类型的变量,指向待拷贝空间的地址处

source

const void* 指针类型的变量,指向拷贝内容的空间地址处

num

size_t类型的变量 , 表明我要拷贝多少个字节数的内容

2.3 memmove()函数的使用案例

案例一:拷贝整形数据

案例一

案例二:拷贝字符型数据

案例二

相信通过上述例子,你已经学会了如何使用memmove()函数。

3. memmove()函数的模拟实现

又到本文最精彩的时候了,函数的模拟实现。

以下是编程思路:

编程思路

下面是实现代码(可以对着思路理解代码):

模拟实现的代码

4. 总结

在本文中,我介绍了memcpy与memmove两个函数的差异、memmove函数的使用及其模拟实现。

希望读者们下来好好理解消化。

本文标签: 打开C语言常用的内存函数大门(二) memmove()函数 (内含memmove的讲解和模拟实现)