10分钟让你学会内存函数:memcpy,memmove,memset,memcmp的用法及模拟实现。

目录:内存操作函数

一:memcpy函数(内存拷贝)

二:memmove函数(内存拷贝)

三:memset函数(内存设置)

四:memcmp函数(内存比较)

一:memcpy函数

memcpy内存函数的实现原理:                                                                                                     

将 num 个字节的数据从 source 指向的位置开始拷贝到 destination 指向的内存块中,这个函数在遇到0’的时候并不会停下

所以memcpy函数中需要传入三个参数,分别是目标内存空间的首地址,被拷贝内存空间的首地址和拷贝字节数。

 memcpy函数可以拷贝字符串数据,整形数组数据,结构体数据等诸多类型......,但因为memcpy内存函数不能够自身拷贝,memcpy函数不能够拷贝内存重叠区的数据,因此存在着一定的局限性,在这里,小夏推荐大家在遇到数据拷贝时应用接下来的memmove函数可以完美的避免所有的不稳定因素。

二:memmove函数

memmove内存函数的实现原理(内存存在重叠,无重叠都可使用): 

用于拷贝内存数据,如果目标区域和源区域有重叠的话,
memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中
但复制后源内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同

memmove函数实现重叠内存过程:

 总结来说,在遇到内存重叠的情况下分为三中情况:

1.从前向后拷贝(内存空间存在重叠)->如果source的地址高于disnation的地址:则进行常规的赋值,及从source的地址依次向后对disnation地址进行拷贝,直到拷贝的字节数达到size_t num,及拷贝完成。

2.从后向前拷贝(内存空间存在重叠)->如果source的地址低于disnation的地址:则进行逆序的赋值,及从source+num的地址向前对disnation+num地址进行拷贝,直到拷贝的字节数达到size_t num,及拷贝完成。

3.从前向后拷贝或-从后向前拷贝都可(内存空间不存在重叠)

 模拟实现memmove函数:

我们可以自己写一个my_memmove函数来模拟实现memmove函数的功能

首先定义函数void* my_memmove(void* s1, const void* s2, size_t len)

因为memmove是拷贝内存的函数,对于内存中被拷贝的是什么数据类型,并没有限制,所以传入的参数数据类型用void*,返回值也是无类型的地址。

size_len是一个无符号整数类型,表示想要拷贝的字节数,所以在my_memmove函数内部,我们可以这样写

#include<stdio.h>
#include<assert.h>
void* my_memmove(void* s1, const void* s2, size_t len)
{
	assert(s1);
	assert(s2);
	void* ret = s1;
	int i = 0;
	
	if (((char*)s2)>((char*)s1))//从s2的前端依次拷贝
	{
		for(i=0;i<len;i++)
		{
			*((char*)s1) = *((char*)s2);
			(char*)s1 = (char*)s1 + 1;
			(char*)s2 = (char*)s2 + 1;
		}
	}
	else
	{
		while (len--)//从s2的后端开始拷贝
			{
				*((char*)s1 + len) = *((char*)s2 + len);
			}
	}

	return ret;
}
int main()
{
	
	int arr[20] = { 0 };
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		arr[i] = i + 1;
	}
	my_memmove(arr + 1, arr , sizeof(int) * 5);
	for (i = 0; arr[i] != 0; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

三:memset函数

memset内存函数的实现原理:num字节对内存块进行初始化 

将value的值依次从ptr地址,依次向后size_t num个字节的内存空间进行赋值

memset的函数定义:

模拟实现memset函数:

我们可以自己写一个my_memset函数来模拟实现memset函数的功能

首先定义函数void* my_memset(void * ptr, int value, size_t num)

因为memset是拷贝内存的函数,对于内存中被拷贝的是什么数据类型,并没有限制,所以传入的参数数据类型用void*,返回值也是无类型的地址。

size_num是一个无符号整数类型,表示想要赋值的字节数,所以在my_memset函数内部,我们可以这样写

#include<stdio.h>
void* my_memset(void* ptr, int value, size_t num)
{
	while (num--)
	{
		*((char*)ptr) = value + '0';
		ptr = (char*)ptr + 1;
	}
}
int main()
{
	char arr[] = "abcdefghijk";
	my_memset(arr+1, 6, 3);
	printf("进过赋值后的结果->%s\n", arr);
	return 0;
}

在模拟实现memset函数中有一个小小的知识点就是:将数字转化成字符该如何转化,字符‘0’的ASCLL值为48,数字0的ASCLL值为0,所以将数字加上字符‘0’就可得到相应的字符

该函数实现的结果为:

四:memcmp函数

memcmp内存函数的实现原理:用于比较比较内存的前N个字节

字符串大小的比较是以ASCII 码表上的顺序来决定,次顺序亦为字符的值。memcmp()首先将s1 第一个字符值减去s2 第一个字符的值,若差为0 则再继续比较下个字符,若差值不为0 则将差值返回。

两个字符串内容完全一样,返回0;

若S1大于S2,则大于0,

反之则小于0;

memcmp的函数定义:从ptr1内存空间和ptr2内存空间依次向后进行比较size_t num个字节大小,且per1和ptr2进const修饰不可改变其内容。

模拟实现memcmp函数:

我们可以自己写一个my_mecmp函数来模拟实现memcmp函数的功能

首先定义函数void* my_memcmp(const void*ptr1,const void*ptr2,size_t num)

#include<stdio.h>
void* my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	while (num--)
	{
		if (*(char*)ptr1 == *(char*)ptr2)
		{
			ptr1 = (char*)ptr1 + 1;
			ptr2 = (char*)ptr2 + 1;
		}
		else
		{
			return *(char*)ptr1 - *(char*)ptr2;
		}
	}
}
int main()
{
	char s1[] = "abcd456ef";
	char s2[] = "abef789nmn";
	int ret=my_memcmp(s1, s2, 5);
	printf("差值为->%d", ret);

	return 0;
}

其执行结果为:

执行结果:

my_memcmp(s1+7, s2,5):1 //字符串s1>字符串s2, 返回正值

my_memcmp(s1, s2,5):-1 // 字符串s1<字符串s2,返回负值

my_memcmp(s1, s2,2):0 //字符串s1=字符串s2, 返回0

如果觉得文章不错,期待你的一键三连哦,你个鼓励是我创作的动力之源,让我们一起加油,顶峰相见!!!

猜你喜欢

转载自blog.csdn.net/smile_sundays/article/details/131859452