【C语言】搞懂内存函数

引言

本文介绍memcpy的使用和模拟实现、memmove的使用和模拟实现、memcmp使用、memset使用

 158c3f50b199454985017a51dbef9841.png               ✨ 猪巴戒:个人主页✨

               所属专栏:《C语言进阶》

        🎈跟着猪巴戒,一起学习C语言🎈

目录

引言

memcpy

memcpy的使用

memcpy的模拟实现

memmove

memcpy函数不用来处理重叠的内存的数据拷贝:

memmove的模拟实现

 总结:

 模拟实现代码

memcmp

memset

memcpy

void * memcpy ( void * destination, const void * source, size_t num )
  • memcpy的作用就是将source的内容拷贝到destination
  • num说明了拷贝多少个字节
  • 返回值是destination.

memcpy的使用

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	memcpy(arr2, arr1, 20);
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

5832dc2659294508bad478215341d1aa.png

memcpy的模拟实现

 内存函数就是无论是什么类型的数据都可以使用。

void* ,属于通用类型的指针,可以存放任意类型的地址。

assert,断言,保证dest和source不是空指针。

num是需要拷贝的字节数。

通过将地址转化为(char*)的形式,将需要拷贝的内容一个字节一个字节地将它们拷贝,就可以实现各种数据的拷贝。

然后dest转移到下一个字节,source转移到下一个字节,知道拷贝完num个字节算结束。

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* source, size_t num)
{
	assert(dest && source);
	void* start = dest;
	while (num--)
	{
		*(char*)dest = *(char*) source;
		dest = (char*)dest + 1;
		source = (char*)source + 1;
	}
	return start;
}

memmove

void * memmove ( void * destination, const void * source, size_t num )
  • 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
  • 参数和memcpy是一样的。 

memcpy函数不用来处理重叠的内存的数据拷贝:

将arr1数组改成{1,2,1,2,3,4,5,8,9,10},从第三位元素开始,拷贝自己的第一到第五个元素

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* source, size_t num)
{
	assert(dest && source);
	void* start = dest;
	while (num--)
	{
		*(char*)dest = *(char*) source;
		dest = (char*)dest + 1;
		source = (char*)source + 1;
	}
	return start;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memcpy(arr1 + 2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

70351ed1ff4a4ba599115e7b0678b91b.png

memcpy在重叠内存拷贝的时候,第三个元素被改成1,第四个元素被改成2,

而第五个元素本来是应该赋值为3的,但是第三个元素已经被改成1了。

第六个元素本来是由第四个元素重新赋值,但是第四个元素被改成了2.

39380881c7a64356adb8af265f088548.png

memmove的模拟实现

如果说我们要将红色部分拷贝到蓝色部分

从前向后拷贝不行,我们要将红色的部分拷贝到蓝色的部分,先将第一个元素拷贝到第三个元素,红色区域的内存被改变,等到将第三个元素拷贝到第五个元素的时候,第三个元素已经发生改变。

从后向前拷贝,如果我们可以先将第五个元素拷贝到第七个元素,这样红色的三、四、五元素先拷贝完后被改变就可以把数值3,4,5成功传到第五、六、七个元素。

25c5324f1eb04ea586499ddf3238b85c.png

 这一次,

从后向前拷贝不行,我们要将红色部分拷贝到蓝色的部分,先将第七个元素拷贝到第五个元素,首先改变了第五个元素的内容,到时候第五个元素还要对第三个元素进行拷贝。

从前向后拷贝,如果我们先将第三个元素拷贝到第一个元素,等轮到第三个元素进行拷贝的时候,第三个元素里的内容已经转出去了,转到第一个元素了,那么第三个元素的内容就可以随便修改了。

ce3a5a681399471bb10ed37671736832.png

 总结:

为了保证source中的数据在拷贝之前就被修改,

  • 当dest在source的右边的时候,采用从后向前的方式
  • 当dest在source的左边的时候,采用从前向后的方式

 模拟实现代码

#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* source, size_t num)
{
	assert(dest && source);
	void* start = dest;
	if (dest < source)
	{
		//从前向后
		while (num--)
		{
			*(char*)dest = *(char*)source;
			dest = (char*)dest + 1;
			source = (char*)source + 1;
		}
	}
	else
	{
		//从后向前拷贝
		while (num--)
		{
			*((char*)dest + num) = *((char*)source + num);
		}
	}
	return start;
}

memcmp

可以比较任意类型的数据

int memcmp ( const void * ptr1, const void * ptr2, size_t num )
  • ptr1指向的第一个空间
  • ptr2指向的第二块空间
  • ptr1和ptr2之间的内存比较
  • num表示需要比较的字节大小

63c51fcf34ab485697e73736e1b3cf45.png

 arr1和arr2比较,arr1比arr2小,返回小于0的数值。

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,3,2 };
	int ret = memcmp(arr1, arr2, 12);
	printf("%d", ret);
	return 0;
}

7da67d9fc3684a7ab9f8ec3fd30040bb.png​ 

memset

void * memset ( void * ptr, int value, size_t num )
  • ptr需要填充的地址空间
  • value,填充什么字符
  • num,填充几个字节
#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "hello world";
	memset(arr, 'x', 5);
	printf("%s\n", arr);
	return 0;
}

92ad5e3e260e4e8988224f64fb739406.png

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
社会演员多的头像社会演员多普通用户
上一篇 2023年12月11日
下一篇 2023年12月11日

相关推荐