memcpy和memmove函数的区别

文章目录

前言

memcpy函数

 memmove函数

memcmp函数


前言

        c语言<string.h>库里面有很多的字符函数,比如memcpy,memmove,memcmp等,这些函数是从内存层面来进行拷贝、比较等等,其中memcpy和memmove函数十分相似,但是又不完全相同,memcpy是假定要操作的两块内存无重叠部分,而memmove则是要操作的两块内存有无重叠部分均可。

memcpy函数

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

        这是对memcpy函数的声明,可以明确看出,其返回的是void*类型的指针,并且有三个参数,第一个参数表示目标地址,第二个参数表示源地址,第三个参数表示拷贝大小(单位是字节)。

        此函数代表着,在内存空间中,从source指向的空间开始,往后一共num个字节的内存空间,将这些空间里面的内容拷贝到 从destination指向的空间开始,往后一共num个字节的内存空间。

         从下方代码和运行结果不难看出其逻辑。

#include <stdio.h>
#include <string.h>
int main()
{
	char name[40];
	char myname[] = "Pierre de Fermat";

	memcpy(name, myname, strlen(myname) + 1);//+1是因为要拷贝\0

	int arr1[10] = {0};
	int arr2[5] = {4,2,55,88,3};
	memcpy(arr1+3, arr2, sizeof(arr2));  //arr1是 arr1[10]这个数组首元素的地址,+3就是跳过3个int类型的数据

	printf("%s\n",name);

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

	return 0;
}

          其写法如下,此函数是一个字节一个字节拷贝内存的,所以如果两块空间有重叠部分,那么就会造成错误,如下图所示:

void* my_memcpy(void* dest, const void* src, const int size)
{
	assert(dest);
	assert(src);
	char* dest1 = (char*)dest;
	char* src1 = (char*)src;
	for (int i = 0;i < size;i++)
	{
		*dest1++ = *src1++;
	}
	return dest;
}

        如下, 从arr1开始,往后20个字节的内容,一个字节一个字节拷贝给arr+2开始,往后20个字节的空间。但是拷贝了8个字节的内存(可以理解为拷贝了两个int类型的数据)之后,函数内部dest的指针指向了原数组中“5”这个数字存储空间的第一个字节,而src的指针指向了原数组“3”这个数字存储空间的第一个字节,但是此时的“3”已经被前面的操作修改成了1,所以从这里开始一个字节一个字节复制,实际上是复制的1,所以“5”的地方被改成了1。而这样拷贝了四个字节的内存之后(step3->step4,如下面过程图的第二张),开始了原数组“4”的内容拷贝到原数组“6”的内容,但是原数组“4”,已经被改成了“2”,拷贝四次之后,一个int类型的数据被拷贝完,step4->step5,然后又重复之前的拷贝,具体步骤见下方第一张过程图片(一个格子代表一个int数据的内存,不是一个字节)。

 

 

 

 memmove函数

         memmove函数相当于是memcpy函数的升级版,考虑了两块空间重叠的问题,其写法如下:

void* my_memove(void* dest,const void* src,const int size)
{
	assert(dest);
	assert(src);
	char* dest1 = (char*)dest;
	char* src1 = (char*)src;
	if (dest < src)//从前向后拷贝    
	{
		for (int i = 0;i < size;i++)
		{
			*dest1++ = *src1++;
		}
	}
	else //从后向前拷贝
	{
		for (int i = size - 1;i >= 0;i--)
		{
			*(dest1 + i) = *(src1 + i);
		}
	}
	return dest;
}

         重叠的情况分为两种,一种是目标空间起始位置在源空间起始位置的前面,另一种情况是目标空间起始位置在源空间起始位置的后面。对于前者,只需要从源空间起始位置开始往后拷贝设定的大小即可,但是对于后者,就应该从源空间末尾处开始,从后往前拷贝设定大小的内容,如下图,很容易看出来。

         如果说memmove是一个有着100分功能的函数,那么memcpy就是有60分的函数,其只适用于两块空间未重叠的情况,而memmove任何情况都使用。

memcmp函数

void* memove(void* dest,const void* src,const int size);

        memcmp函数和strcmp函数类似,也是从两个指针指向的地址,一个字节一个字节比过去,比较size个字节的内容,不过memcmp函数可以比较其他的数据类型,不仅限于字符型数据,如下。

#include <stdio.h>
#include <string.h>

int main()
{
	int a = 5;
	int b = 4;
	int* dest = &a;
	int* src = &b;
	int ret = memcmp(dest, src, 4);
	if (ret < 0)
		printf("<");
	else if (ret > 0)
		printf(">");
	else printf("=");

	return 0;
}

 

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力努力再努力.xx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值