前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅谈内存函数以及模拟实现

浅谈内存函数以及模拟实现

作者头像
用户10923087
发布2024-01-23 14:16:34
1120
发布2024-01-23 14:16:34
举报
文章被收录于专栏:我的计算机成长

1.memcpy

代码语言:javascript
复制
void * memcpy ( void * destination, const void * source, size_t num );

函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。 这个函数在遇到 '\0' 的时候并不会停下来。 如果source和destination有任何的重叠,复制的结果都是未定义的。

 接下来我们使用一下这个函数:

代码语言:javascript
复制
#include<string.h>
int main()
{
	int arr1[10] = { 0 };
	int arr2[] = { 1,2,3,4,5 };
	memcpy(arr1, arr2, 20);
	return 0;
}

 经过调试之后可以发现arr1里面存放了1,2,3,4,5,这个就是memcpy的基本用法。

2.模拟实现memcpy

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<string.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	while (num)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
		num--;
	}
}
int main()
{
	int arr1[10] = { 0 };
	int arr2[] = { 1,2,3,4,5 };
	my_memcpy(arr1, arr2, 20);
	return 0;
}

src里面的内容是不会被改变的,所以使用const限制一下。num是拷贝的字节数,我们每次拷贝一个字节。先使用while循环,循环num次,每次num--,dest和src是void*的指针,我们强制类型转换为char*的指针,然后解引用,将src赋给dest,dest和src这时就应该往后走一个字节,因为强制类型转换是临时的,所以还是需要强制类型转换为char*,然后+1。

当我们想把1,2,3,4,5放到3,4,5,6,7的位置上时就会出现问题,当空间不重叠内存的时候使用memcpy是可以的,像这种不重叠内存的拷贝需要使用memmove。

代码语言:javascript
复制
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(arr + 2, arr, 20);
	return 0;
}

 3.memmove

代码语言:javascript
复制
void * memmove ( void * destination, const void * source, size_t num );

和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

代码语言:javascript
复制
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(arr + 2, arr, 20);
	return 0;
}

 使用memmove的话就能很好的解决上面的问题。


4.模拟实现memmove

我们先来想一下,如果有一个数组:

代码语言:javascript
复制
int arr[]={1,2,3,4,5,6,7,8,9,10};

假如我们要把1,2,3,4,5拷贝到3,4,5,6,7这个位置上去,使得数组变成:

代码语言:javascript
复制
int arr[]={1,2,1,2,3,4,5,8,9,10};

那我们就需要先将5放在7的位置上,4放在6的位置上,以此类推,才能达到效果,也就是从后向前拷贝。

如果我们要把3,4,5,6,7拷贝到1,2,3,4,5这个位置上,就要先将3放到1的位置上,以此类推,也就是从前往后拷贝。

所以说拷贝的方式会根据需求而改变。

那么什么时候从前往后拷贝,什么时候从后往前拷贝呢?

还是用一个数组举例:

代码语言:javascript
复制
int arr[]={1,2,3,4,5,6,7,8,9,10};

如果dest这块空间在src这块空间的左边且重叠,也就是要把高地址的数据拷贝到低地址处,就需要从前往后拷贝。 如果dest这块空间在src这块空间的右边且重叠,也就是要把低地址的数据拷贝到高地址处,就需要从后往前拷贝。 如果dest这块空间和src这块空间不重叠,不管从前往后还是从后往前都是可以的,当然是在空间充足的情况下,不能越界。


 一开始我们还是需要保存起始位置的地址,用作返回值。使用if判断dest是否小于src,如果小于则进入for循环,循环sz次,这里的方法是跟上面的memcpy一样的。当dest>src时,我们使用while循环比较方便,因为我们从后向前拷贝是先将后面的数据开始,所以当我们将条件设置成sz--时,由于是后置--,也是循环sz次,但是*((char*)src + sz)就刚好能够拿出最后一个数据拷贝到*((char*)dest + sz),当然使用for循环也是可以的。

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* dest,const void* src,size_t sz)
{
	assert(dest && src);
	void* ret = dest;
	if (dest < src)//从前向后
	{
		for (int i = 0; i < sz; i++)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest+1;
			src = (char*)src + 1;
		}
	}
	else//从后向前
	{
		while (sz--)
		{
			*((char*)dest + sz) = *((char*)src + sz);
		}
	}
	return ret;
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr, arr + 2, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

5.memset

代码语言:javascript
复制
void * memset ( void * ptr, int value, size_t num );

 这个函数就是将ptr指向的前num个字节的数据设置成指定的值(value),再把起始位置返回。

下面是memset的使用: 

代码语言:javascript
复制
int main()
{
	char arr[] = "hello world";
	memset(arr + 6, 'x', 3);
	printf("%s\n", arr);
	return 0;
}

 但是要注意的是num的单位是字节。如果我们想要把这个数组的内容设置成10个1,像下面这样就已经出错了,这样是把每个字节都设置成1,而不是整型。

代码语言:javascript
复制
int main()
{
	int arr[10] = { 0 };
	memset(arr, 1, 40);
	return 0;
}

6.memcmp

代码语言:javascript
复制
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

 memcmp这个函数就是比较两块空间的前num个字节的内容,如果一样则返回0,小于则返回<0,大于则返回>0。需要注意的是在比较时也是一对字节进行比较,和strcmp的区别就是strcmp是进行字符的比较,而memcmp是进行内存块的比较。

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 1,2,3,4 };
	int ret=memcmp(arr1, arr2, 16);
	printf("%d ", ret);
	return 0;
}

今天的分享到这里就结束啦!谢谢老铁们的阅读,让我们下期再见。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-01-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.memcpy
  • 2.模拟实现memcpy
  •  3.memmove
  • 4.模拟实现memmove
  • 5.memset
  • 6.memcmp
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档