内存函数的介绍和模拟实现

目录

1.memcpy的使用(内存拷贝)

2.memcpy的实现

3.memmove的使用(内存拷贝)

 4.memmove的实现

5.memset 的使用(内存设置)

6.memcmp的使用(内存比较)


1.memcpy的使用(内存拷贝)

void * memcpy ( void * destination, const void * source, size_t num );
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 '\0' 的时候并不会停下来。可能把字符'\0'也拷贝过去
  • 如果source和destination有任何的重叠,复制的结果都是未定义的

注意:对于拷贝时候内存存在重叠的情况,尽量不要使用memcpy。

#define  _CRT_SECURE_NO_WARNINGS 1
#include
#include 
//memcpy的使用
struct {
	char name[40];
    int age;
    person, 
    person_copy
       };
int main()
{
	char myname[] = "Pierre de Fermat";

	memcpy(person.name, myname, strlen(myname) + 1);//将‘\0’也拷贝过去

	person.age = 46;

	memcpy(&person_copy, &person, sizeof(person));

	printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);

	return 0;
}

将myname数组中的数据拷贝到person.name中。

2.memcpy的实现

我们使用对内存进行操作的函数。因此我们应当想到为了在处理不同数据类型时候一个函数便能解决大部分问题,因此我们可以看出内存函数的参数和返回值大部分都是void类型,并且我们在对内存操作时想到的是对内存一个字节一个字节进行操作。

#include
void* my_memcpy(const void* des, const void* src, size_t num)
{
	assert(des && src);
	const void* ret = des;
	//一个字节一个字节拷贝过去由此我们想到了char * 类型数据
	//数据拷贝
	int i = 0;
	for (i = 0; i < num; i++)
	{
		*(char*)des = *(char*)src;//转换类型便于对内存进行一个字节的操作
		des = (char*)des + 1;
		src = (char*)src + 1;
	}

	return ret;
}
int main()
{
	char name1[20] = "zhouhaotianxxx";
	char name2[] = "wangxilong";
	//使用模拟的memcpy函数实现将name2中的数据拷贝到name1中

	puts("name1最初的字符串是:zhouhaotian\0");
	printf("name1中的数据经过拷贝后变成了:%s\n", my_memcpy(name1, name2, strlen(name2))); //注意memcpy函数在遇到 '\0' 的时候并不会停下来,他是忠心以字节个数来进行拷贝的
	return 0;
}

内存函数的介绍和模拟实现_第1张图片

3.memmove的使用(内存拷贝)

void * memmove ( void * destination, const void * source, size_t num );
  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理
#define  _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include

void* memmove(void* destination, const void* source, size_t num);
 
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
 
如果源空间和目标空间出现重叠,建议使用memmove函数处理。
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(arr, arr + 5, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	return 0;
}//可以看出在vs2022下memcpy也可以对源空间和目标空间出现重叠情况进行处理。

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr, arr + 5, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	return 0;
}//如果源空间和目标空间出现重叠,建议使用memmove函数处理。

 4.memmove的实现

由于我们知道了memcpy函数无法对内存块重叠情况下进行内存拷贝,由此我们需要使用或者实现一个新的函数能够完成此情况下的功能实现。

我们先画图分析一下:

内存函数的介绍和模拟实现_第2张图片

 我们可看到当源头指针和目的地指针在指向同一块内存空间的内容时,他们两指向的前后顺序将会影响我们内存的拷贝。

第一种:

内存函数的介绍和模拟实现_第3张图片

  •  src在dst之前,并且两者内容存在重叠的情况下:当我们仍然从前往后拷贝内容会发现我们想要拷贝的内容将会被覆盖,因此这种情况下我们应当从后往前拷贝。

 

内存函数的介绍和模拟实现_第4张图片

  •  src在dst之后,并且两者内容存在重叠的情况下:当我们从后往前拷贝内容会发现我们想要拷贝的内容将会被覆盖,因此这种情况下我们应当从前往后拷贝。 

  •  而当内容并无内存重叠情况下我们从前往后拷贝或者从后往前拷贝便可以根据我们个人意愿来实现如何拷贝,下面给出代码实现。
#include
#include
#include

void* my_memmove(const void* dst, const void* src, size_t num)
{
	assert(dst && src);
	const void* ret = dst;
	//一个字节一个字节拷贝
	//数据拷贝
	int i = 0;
	//从后往前拷贝
	if (dst > src)
	{
		src = (char*)src + num - 1;
		dst = (char*)dst + num - 1;
		for (i = 0; i < num; i++)
		{
			*(char*)dst = *(char*)src;
			dst = (char*)dst - 1;
			src = (char*)src - 1;
		}
	}
	//从前面往后面拷贝
	if (dst <= src)
	{

		for (i = 0; i < num; i++)
		{
			*(char*)dst = *(char*)src;
			dst = (char*)dst + 1;
			src = (char*)src + 1;
		}
	}
	return ret;
}
int main()
{

	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr, arr + 2, 8);//模拟实现重叠内存拷贝函数

	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	//结果应该是3 4 3 4 5 6 7 8 9 10
	printf("\n");


	return 0;
}

内存函数的介绍和模拟实现_第5张图片

5.memset 的使用(内存设置)

void * memset ( void * ptr, int value, size_t num );
  • 这个函数用于将 prt 指向的内存区域的前 num 个字节设置为 value 指定的值。它返回 ptr 的起始地址。
#define  _CRT_SECURE_NO_WARNINGS 1
#include
#include

//memset的使用
//以字节为单位设置内存
int main()
{
	char arr[] = "hello world";
	memset(arr + 2, 'x', 3);
	printf("%s\n", arr);
	return 0;
}

内存函数的介绍和模拟实现_第6张图片

注意:memset是以字节为单位来设置内存的 !

6.memcmp的使用(内存比较)

int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • 比较从ptr1和ptr2指针开始的num个字节
  • 返回值是int类型

返回值如下图:

内存函数的介绍和模拟实现_第7张图片

  • memcmp比较比较的是内存块(可以指定比较字节数)
  • 而strcmp只能比较字符串

 

#define  _CRT_SECURE_NO_WARNINGS 1
#include
#include
//memcmp的使用
int main()
{
	int a[] = { 1,2,3,4,5,6,7 };
	int b[] = { 1,2,3,5, };
	printf("%d\n", memcmp(a, b, 12));
	printf("%d\n", memcmp(a, b, 16));
	return 0;
}

内存函数的介绍和模拟实现_第8张图片


希望大佬们一键三连,您的支持是对我最大的鼓励! 

你可能感兴趣的:(C语言进阶,c++,开发语言,c语言,库函数)