内存操作函数【快速了解内存函数的作用和实现】


前言

对于字符串有一系列的字符串函数来操作字符串,比如strcpy、strcmp、strstr。但是这些函数都是只能用来操作字符串的,如果我们想要用来操作其他类型的数据的话就会有问题。这时就有一系列的内存操作函数来供我们使用,帮助我们更好地进行开发和工作。


内存操作函数的共性

我们先来找一找内存操作函数的共性,首先是看函数的定义部分,观察他们的返回类型,还有参数类型。

memcpy 函数的定义

在这里插入图片描述

memmove 函数的定义

在这里插入图片描述

memcmp 函数的定义

在这里插入图片描述

函数的共性

可以这些函数在定义的时候都是将需要操作的空间的使用void* 类型的形参来接受,为什么需要使用 void* 类型的指针来接受这个参数呢,这是因为函数的实现这并不知道会有什么类型的数据传进来,所以需要将函数的参数设为 void* 类型的指针(可以转变和接收为任意类型的指针)。而这些函数在传参的时候都会有一个size_t num 这是说明函数需要操作的空间大小,单位是字节。由于函数在实现的时候,操作的是空间大小的单位是字节。所以在模拟实现的时候就需要将指针转化为字符指针,因为字符指针刚好是一个字节一个字节操作的。

memcpy 函数【内存拷贝函数】

memcpy函数的定义

既然是函数,我们就需要将函数的返回类型还有参数的类型搞清楚,这样可以帮我们更好地掌握这个函数。
memcpy函数的定义

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

memcpy 函数,是将源空间后面的num个字节拷贝到目标空间后面的num个字节上。

模拟实现memcpy 函数

我们只需要将从source开始到source + num - 1 的数据拷贝到从destination 开始,到destination + num - 1 的地址上去就可以了。

void* my_memcpy(void* dest, const void* src, size_t count) {
	assert(dest && src); 	//判断指针不是空指针
	void* ret = dest;		//保留目标空间的起始位置
	while (count--) {	//控制循环保持在0 ~ count - 1
		*(char*)dest = *(char*)src;		//将源空间的内容一个字节一个字节地拷贝到目标空间
		(char*)dest = (char*)dest + 1; 	  //目标空间指向目标空间的下一个字节的地址
		(char*)src = (char*)src + 1;	  //源空间指向源空间的下一个字节的地址
	}
	return ret;     //返回目标空间的起始地址
}

使用前
在这里插入图片描述

使用后
在这里插入图片描述

memmove 函数

memcpy 函数在实现的时候如果目标空间和源空间存在空间重叠,那么就有可能将目标空间的值改变,然后拷贝到后面的目标空间。这样就达不到想要的效果。

使用前
在这里插入图片描述

使用后
在这里插入图片描述

所以需要一个memmove 来解决这一问题

memmove 函数的定义

memmove 函数的定义

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

memmove 函数的模拟实现

解决这一问题,我们可以将源空间的内容拷贝到一个额外的空间里面,然后将这个额外的空间赋给目标空间,但是这种方法就需要额外的空间还有时间,效率有点低。所以我们需要一种更高效的方法,可以看到,如果目标空间的起始地址大于源空间的起始地址的时候,只需要从后面往前拷贝就行了,当目标空间的起始小于起始地址的时候,只需要按照从后往前拷贝的方式来拷贝就可以了。这时我们只需要进行一次判断然后执行对应的操作。就可以节省空间和时间了。

void* my_memmove(void* dest, const void* src, size_t count) {
	assert(dest && src);  	//判断指针不为空
	void* ret = dest;		//	保存目标空间的地址
	if (dest > src) {		//判断是目标空间地址是否大于源空间地址
		while (count--) {
			*((char*)dest + count) = *((char*)src + count);	//从后往前拷贝
		}
	}
	else {		//目标空间地址小于源空间地址
		while (count--) {
			*(char*)dest = *(char*)src;		//从前往后拷贝
		(char*)dest = (char*)dest + 1; 	
		(char*)src = (char*)src + 1;	  
		}
	}
	return ret; 	//实现链式访问
}

两个函数之间的差距就在重叠空间的拷贝,虽然现在在一些编译器下memcpy函数也可以实现重叠空间的拷贝,但是并不是全部编译器都可以实现。所以在编写代码的时候就需要严格得将两者分开,保证代码的可移植性。

memcmp 内存比较函数

memcmp 函数的使用可以对比strcmp函数,当空间1的数据小于空间2的数据,就返回下于0的数;两空间相等的话就返回0;当空间1的数据大于空间2的数据,就返回大于0的数。

memcmp 函数的定义

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

memcmp函数的模拟实现这里就不做讲解,可以参考strcmp的实现。


总结

本文仅仅简单得介绍了内存操作函数memcpy、memmove、memcmp,其中还有memcpy、memmove函数的模拟实现供大家参考,希望可以帮助到大家。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_featherbrain

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

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

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

打赏作者

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

抵扣说明:

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

余额充值