内存操作函数介绍及其模拟实现


内存操作函数介绍及其模拟实现


文章目录:

  1. memcpy
  2. memmove
  3. memset
  4. memcmp

前言:

  • 字符串函数对于字符串的很多的操作都提供了很多的方便之处,但其只适用于字符串,而内存操作函数便由此提出。
  • 内存操作函数,通过访问地址的方式来访问相应的对象,其并不关心存储对象的
    类型,可应用于所有类型的对象。
  • 对于字符串类型的相应函数,可参考文章:字符串函数介绍及其模拟实现

编译环境:vs2013


一、memcpy

memcpy文档

void* memcpy ( void* destination, const void* source, size_t num );
  • 作用:将num字节数的值从源指针指向的位置直接复制到目标指向的内存块。
  • 返回:返回目标指针指向的字符串。
  • 源指针和目标指针指向的对象的基础类型与此函数无关,结果是数据的二进制副本。
  • 该函数不检查源指针中的任何终止空字符 ,它总是准确地复制字节数。
  • 为避免溢出,目标和源参数指向的数组大小应至少为字节数,并且不应重叠(对于重叠的内存块,memmove 是一种更安全的方法)。

memcpy模拟实现及测试:

//1.memcpy 在src指向的空间拷贝num字节的数据到dest指向的空间中,不允许重叠
void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* temp = dest;
	//断言:两空间都不为空,为空则报错返回
	assert(dest != NULL);
	assert(src != NULL);
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return temp;
}
//my_memcpy测试函数
void test_my_memcpy()
{
	char* str1[10] = { 0 };
	char* str2 = "mbcd---";
	char* ret = my_memcpy(str1, str2, strlen(str2));
	printf("%s\n", ret);
}

在这里插入图片描述

而当我们对自身进行元素拷贝时程序出现错误。

char* ret = my_memcpy(str2, str2 + 2, 2);

在这里插入图片描述
故:memcpy函数在对自身进行拷贝覆盖时并不能实现,由此提出memmove函数,功能同memcpy且可对自身进行拷贝覆盖。

二、memmove

memmove文档

void* memmove ( void* destination, const void* source, size_t num );
  • 作用:将num字节数的值从源指向的空间位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样,允许目标和源重叠。
  • 返回:返回目标指针指向的字符串。
  • 源指针和目标指针指向的对象的基础类型与此函数无关,结果是数据的二进制副本。
  • 该函数不检查源中的任何终止空字符 ,它总是准确地复制字节数。
  • 为避免溢出,目标参数和源参数指向的数组的大小应至少为字节数。

1 不考虑两空间产生覆盖,处理同memcpy。
在这里插入图片描述
2 考虑两空间产生覆盖时。
在这里插入图片描述
在这里插入图片描述
memmove模拟实现及测试:

//2.memmove 将src指向的空间前num个字节的数据拷贝到dest指向的空间中,允许重叠
void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest != NULL);
	assert(src != NULL);
	void* temp = dest;
	if (dest <= src || (char*)dest >= ((char*)src+num))
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		dest = (char*)dest + num - 1;
		src = (char*)src + num - 1;
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest - 1;
			src = (char*)src - 1;
		}
	}
	return temp;
}
//my_memmove测试函数
void test_my_memmove()
{
	char str[]= "abcdefgh";
	//char* ret1 = my_memmove(str + 1, str + 5, 3);
	//printf("%s\n", ret1);
	//char* ret2 = my_memmove(str + 5, str + 1, 3);
	//printf("%s\n", ret2);
	//char* ret3 = my_memmove(str + 1, str + 3, 4);
	//printf("%s\n", ret3);
	char* ret4 = my_memmove(str + 3, str + 1, 4);
	printf("%s\n", ret4);
}

在这里插入图片描述

三、memset

memset文档

void* memset ( void* ptr, int value, size_t num );
  • 作用:将 ptr 指向的内存块的前num个字节数设置为指定值并返回ptr,常用于数据初始化
  • 返回:返回ptr指针。
  • ptr:指向要填充内存块的指针。
  • value:要设置的值,该值作为 int 传递,但该函数使用此值的无符号 char 转换填充内存块。
  • num:要设置为该值的字节数。

memset模拟实现及测试:

//3.memset 将ptr中前num个字节用value填充,并返回ptr
void* my_memset(void* ptr, int value, size_t num)
{
	assert(ptr != NULL);
	void* temp = ptr;
	while(num--)
	{
		*(char*)ptr = value;
		ptr = (char*)ptr + 1;
	}
	return temp;
}
//my_memset测试函数
void test_my_memset()
{
	char str[]= "abcdef";
	char* ret = my_memset(str, '*', 3);
	printf("%s\n", ret);
}

在这里插入图片描述

四、memcmp

memcmp文档

int memcmp ( const void* ptr1, const void* ptr2, size_t num );
  • 作用:比较两内存块,将两指针指向的前num个字节进行一一比较。
  • 返回:
  • ptr1>ptr2,返回一大于0的数;
  • ptr1=ptr2,返回0;
  • ptr1<ptr2,返回一个小于0的数。
  • 注意,与 strcmp 不同地方为,memcmp在找到空字符后并不会停止比较.。

memcmp模拟实现及测试:

//4.memcmp ptr1与ptr2的前num个字节数据进行比较
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	assert(ptr1);
	assert(ptr2);
	char* temp1 = (char*)ptr1;
	char* temp2 = (char*)ptr2;
	while (num--)
	{
		if (*temp1 == *temp2)
		{
			temp1++;
			temp2++;
		}
		else
		{
			if (*temp1 > *temp2)
				return 1;
			else
				return -1;
		}
	}
	return 0;
}
//my_memcmp测试函数
void test_my_memcmp()
{
	char* str1 = "ab";
	char* str2 = "abcdef";
	int n1 = my_memcmp(str1, str2, 2);
	if (n1 > 0)
		printf("str1>str2\n");
	else if (n1 < 0)
		printf("str1<str2\n");
	else
		printf("str1=str2\n");
}

在这里插入图片描述


五、总结

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值