文章目录
- 1. 前言
- 2. memmove()函数
- 2.1 memmove()函数与memcpy()函数的差异
- 2.2 memmove()函数的原型
- 2.3 memmove()函数的使用案例
- 3. memmove()函数的模拟实现
- 4. 总结
1. 前言
在之前,我向大家介绍了C语言中的一个常用的内存函数memcpy函数。如果你还没看的话,建议你先去看memcpy函数这篇文章,因为接下来,可能会用到那篇文章的知识甚至会拓展没有讲过的知识。强烈建议先去看把一篇文章,文章链接:memcpy函数讲解及其模拟实现(点此查看即可)
那么在本文中,我将介绍继续介绍C语言中常用的内存函数——memmove()函数。
2. memmove()函数
memmove()函数的作用:将源空间的内容移动到目标空间上,也可以理解为将指定源空间的内容拷贝到目标空间中。
可能看到这里有的读者就会提出这么一个问题:
这不是跟memcpy()函数的功能一样吗?这是不一样的,可不敢将两者给弄混了。
2.1 memmove()函数与memcpy()函数的差异
在我们用memcpy函数时,不知道大家有没有想过这么一个问题:
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()函数的原型
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函数的使用及其模拟实现。
希望读者们下来好好理解消化。
👍👍👍