内存操作函数:memcpy,memmove

前言:在之前的文章中,介绍了一些简单实用的字符串函数,但是这些函数只能对字符串使用,适用性太狭小。所以在本章,将介绍几个内存操作函数,适用于所有类型的数据。

memcpy(拷贝内存块)

cplusplus对其介绍如下:(仅供参考,看不懂英文也没关系)

在这里插入图片描述

由图可知,memcpy函数具有3个参数,第一个为目的地,第二个为源(要拷贝的内容),第三个为想要拷贝的字节数n。
通俗点说:将源(第2个参数)的n(第3个参数)个字节的数值拷贝到目的地(第1个参数)

举以下例子,方便理解(字符串):

#include<stdio.h>
#include<string.h>    //引用字符串函数头文件
int main()
{
    
    
	char arr1[] = "hello friend"; //源
	char arr2[10] = "world";      //目的地
	printf("拷贝前:%s\n", arr2);  //打印拷贝前的arr2数组,便于比较
	memcpy(arr2, arr1, 5);        //将arr1数组的5个字节的数值拷贝到arr2数组
	printf("拷贝后:%s\n", arr2);  //打印拷贝后的arr2数组
	return 0;
}

输出:

在这里插入图片描述

观察上图控制台输出结果,可知arr1数组中的hello拷贝到了arr2数组中,并且将其前五个字节上的值覆盖。由此可见,memcpy可以实现strcpy的功能。

举以下例子,方便理解(整型):

在文章开头,我们说过memcpy的适用性非常广泛,下面再给出拷贝整型的例子,其余类型的拷贝都与此相似。

#include<stdio.h>
#include<string.h>    //引用字符串函数头文件
int main()
{
    
    
	int arr1[] = {
    
     1,2,3,4,5,6,7,8,9,0 }; //源
	int arr2[10];                         //目的地
	memcpy(arr2, arr1, 40);               //将arr1数组的40个字节的数值拷贝到arr2数组
	for (int i = 0; i < 10; i++)         
	{
    
     
		printf("%d ", arr2[i]);           //打印拷贝后的arr2数组
 	}

}

输出:
在这里插入图片描述

使用时注意事项:

1.第3个参数的单位是字节,使用时要考虑数据类型。
2. 目的地必须是可变的,比如常量字符串不可变,不能作为目的地
3.目的地必须足够大,能够存放的下拷贝的内容

模拟实现memcpy

通过代码模拟实现memcpy的功能,让大家明白memcpy函数的原理,便于更好的掌握使用。

void* my_memcpy(void* dest, const void* rce, size_t num)
{
    
    
	void* p = dest;    //记录其目的地起始地址,便于返回
	while (num--)      //进行num个循环
	{
    
    
		*(char*)dest = *(char*)rce;    //逐字节赋值
		dest = (char*)dest+1;          //目的地地址向后跳一字节
		rce = (char*)rce + 1;          //源地址向后跳一字节
	}
	return p;        //返回目的地起始地址
}

memcpy虽然好用,但是它也有缺陷,在内存重叠的时候,可能会出现意想不到的情况,具体请看以下代码:

#include<stdio.h>
#include<string.h>    //引用字符串函数头文件
int main()
{
    
    
	int arr1[] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	memcpy(arr1+2, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
    
    
		printf("%d ", arr1[i]);
	}
	return 0;
}

理想打印出来的应该是1,2,1,2,3,4,5,8,9,10

但是输出结果为:
在这里插入图片描述
出现这种输出的原因:
在这里插入图片描述

因此,当内存重叠时,不适合使用memcpy函数(某些IDE中就算重叠也不会出现上述情况,但出于严谨,最好还是不要这么使用),下面,我们请出memmove函数,它的功能与memcpy类似,但是支持拷贝重叠部分

memmove(移动内存块)

cplusplus对其介绍如下:(仅供参考,看不懂英文也没关系)

在这里插入图片描述

由图可知,memmove函数具有3个参数,第一个为目的地,第二个为源(要复制的内容),第三个为想要复制的字节数n。
通俗点说:将源(第2个参数)的n(第3个参数)个字节的数值复制到目的地(第1个参数),总体来说与memcpy无差别,但memmove允许目的地和来源重叠。

使用时注意事项:

1.第3个参数的单位是字节,使用时要考虑数据类型。
2. 目的地必须是可变的,比如常量字符串不可变,不能作为目的地
3.目的地必须足够大,能够存放的下拷贝的内容

模拟实现memmove

通过代码模拟实现memmove的功能,让大家明白memmove函数的原理,便于更好的掌握使用。

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);
		}
	}
}

将memmove模拟实现的代码与memcpy模拟实现的代码比较,可以看出两者前半部分差不多,但memmove比memcpy多了后半部分当目的地地址大于来源地址时,从后向前赋值的情况,因此它允许目的地和来源重叠。

总结:

memcpy用于目的地和来源不重叠的情况。
memmove无论目的地和来源重不重叠,都可以使用。
可以说memcpy包含在memmove内。

文末BB:对哪里有问题的朋友,可以在评论区留言,若哪里写的有问题,也欢迎朋友们在评论区指出,博主看到后会第一时间确定修改。最后,制作不易,希望朋友们给点点赞和关注。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_73390155/article/details/129655201