【C语言进阶】 内存函数相关讲解与模拟实现

目录

 

memcpy

模拟实现memcpy

memmove

模拟实现memmove

memcmp

结尾


 

memcpy

由 source指向地址为起始地址的连续n个字节的数据复制到以destination指向地址为起始地址的空间内。格式如下

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

说明: 

1、函数返回一个指向desinationt的指针。搭配头文件#include<string.h>使用

2、source和destination所指内存区域不能重叠

3、与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。

4、strcpy就只能拷贝字符串了,它遇到'\0'就结束拷贝。memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度

5、如果目标数组destination本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址

应用如下:

拷贝结构体代码如下

#include <stdio.h>
#include <string.h>
struct {
	char name[40];
	int age;
} person, person_copy;
int main()
{
	char myname[] = "Pierre de Fermat";
	memcpy(person.name, myname, strlen(myname) + 1);
	person.age = 46;
	memcpy(&person_copy, &person, sizeof(person));
	printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);
	return 0;
}

 结果如下

f5dca0a834f44b618486b045e5cd8c24.png

注意 :source和destination所指内存区域不能重叠。num的单位为字节

模拟实现memcpy

模拟实现memmcpy,只需要从source指向地址为起始地址连续n个字节的数据复制到以destination指向地址为起始地址的空间内即可,注意因为memcpy可以拷贝任何数据,所以这里我们无论函数的返回值还是参数都应该为void*

 my_memcpy格式如下

void* my_memcpy(void* dest, const void* src, size_t num)

实现代码如下

//void* my_memcpy(void* dest, const void* src, size_t num)
//{
//	void* ret = dest;//记录起始地址
//	assert(src && dest);//断言,防止传进来空指针
//
//	while (num--)//循环num次,复制num个字节
//	{
//		*(char*)dest = *(char*)src;//以char*为单位,强制转换为char*
//		dest = (char*)dest + 1;
//		src = (char*)src + 1;
//	}
//	return ret;
//}

 关于强制转换为char*的意义图解

7310367d651243d487a4a2e6d052666d.png

//		dest = (char*)dest + 1;
//		src = (char*)src + 1;

注意: 此处代码不可以用dest++和src++进行代替。原因是虽然上一句代码进行了数据转换,但是那只是临时转换,如果用dest++,那么一次跳过的就不是一个字节了,而是dest所对应的字节;而按照上述代码书写则一次只跳一个字节。

memmove

memmove和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。格式如下

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

说明: 

如果源空间和目标空间出现重叠,就得使用memmove函数处理

cd19352d551544878d484d94ef97df69.png

使用如下 

81d161f4cb3847339b7dfd7dea9bd8a8.png

模拟实现memmove

模拟实现memove只需要想怎么才处理重叠源内存块和目标内存块就好,实现格式如下

void* my_memmove(void* dest, const void* src, size_t num)

这里我们可以分情况进行讨论

cf804bde88284a5c91aa7380b8bd73eb.png

其他情况便可以从前向后进行复制

具体函数实现如下

//void* my_memmove(void* dest, const void* src, size_t num)
//{
//	void* ret = dest;//记录起始地址
//	assert(dest && src);//断言
//
//	if (dest < src)
//	{
//		//前->后
//		while (num--)
//		{
//			*(char*)dest = *(char*)src;
//			dest = (char*)dest + 1;
//			src = (char*)src + 1;
//		}
//	}
//	else
//	{
//		//后->前
//		while (num--)//20
//		{
//			*((char*)dest + num) = *((char*)src + num);
//		}
//	}
//	return ret;
//}

memcmp

比较从ptr1和ptr2指针开始的num个字节 ,可以比较任意类型的数据,格式如下
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

说明:

4990810cd5ab414391202a69c9048619.png

使用如下 

 2d494404ba7f45ed8c7f85f51955e2bd.png

  

结尾

以上就是博主对内存函数的相关讲解和部分模拟实现,讲解有不清楚或者讲错的地方,可以在评论区或者私信博主.看完记得点赞哦!!!

 

 

 

  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

遇事问春风乄

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

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

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

打赏作者

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

抵扣说明:

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

余额充值