C语言快速入门之内存函数的使用和模拟实现

1.memcpy

它可以理解为memory + copy的组合,memory有记忆的意思,这里指的是内存,copy是拷贝,这个函数是针对内存块进行拷贝的

函数原型

void* memcpy(void* destination,const void* source, size_t num);

从source位置开始,向后num个数据拷贝到destination中,它与字符串的strcopy类似,但是遇到'\0'不会停下来,同时,两者的内存不能重叠

我们先来写代码使用一下爱这个函数吧

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };

	my_memcpy(arr2, arr1, 20);	//字节的长度
	int i = 0;
	for (i = 0; i < 20; i++)
	{
		printf("%d ", arr2[i]);
	}

	return 0;
}

在这个代码中,我们将arr1的内容拷贝到了arr2中,拷贝了20个字节,也就是5个int类型的数字,一定要注意是字节的拷贝,这是运行结果

现在,我们来模拟实现这个函数吧

void* my_memcpy(void* dest, void* src, size_t num)
{
	int i = 0;
	void* ret = dest;
	assert(dest && src);
	/*for (i = 0; i < num; i++)
	{
		*((char*)dest + i) = *((char*)src + i);
	}*/

	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

那如果我们想实现在一个数组内进行操作,比如我想操作arr1数组,把第二个数字开始更改,进行拷贝,如果我们写出如下的代码,可能运行结果与我们考虑的就不同了

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;
}

我们想要得到的是 1,2,1,2,3,4,5,8,9,10,但实际结果是:

实际上,这是因为memcpy是不能有内存重叠的,这样我们先更改了,然后再访问,因此出现了很多个1,2

当然,VS有保护机制,我们现在也可以使用memcpy来实现了,但理论上 是不行的

2.memmove

memmove和memcopy的差别是memmove函数处理源内存块和目标内存块是可以重叠的,最后返回目标空间的起始地址

函数原型

void* memmeove(void* dest, const void* src, size_t num)

现在,我们可以运用这个函数来实现了

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

	return 0;
}

现在,我们来看看结果是否和我们想要的一样?

那么,我们是否可以尝试进行模拟这个函数呢?

第一种方法,我们在函数中再创建一个数组,将内容拷贝过去,然后再进行

那我们是否可以不创建新数组,来实现这个函数呢?

事实上,我们可以根据dest和scr的位置来判断

当dest在src之前时,我们从前向后进行拷贝,当dest在src后面时,我们从后向前进行拷贝,因此,我们可以写出以下的代码

void* my_memmeove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	if (dest < src)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}

3.memset

是用来完成内存设置的

函数原型:

void * memset(void* ptr,int vulue,size_t num);

ptr代表要填充的内存块的位置,vulue是设置的值,num是填充几个字节的位置

现在我们来使用这个函数吧!

int main()
{
	char arr[] = "hello world";
	memset(arr, 'x', 5);
	printf("%s ", arr);

	return 0;
}

这里,我们将前五个字符变成了x,结果如下:

当然,也不仅限于字符串函数,整形函数也可以,但是我们需要注意,这里是把所有的字节转换,而int类型占据4个字节,应该注意如何来运用

4.memcmp

完成内存块的比较

函数原型

int memcmp(const void* ptr1, const void* ptr2, size_t num);

从ptr1与ptr2开始num个字节进行比较,返回值是数字,前者大返回大于0的,后者大返回小于0的,相等返回0

我们来使用这个函数吧

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7 };
	int arr2[] = { 1,2,3,4,8,8,8 };
	int ret = memcmp(arr1, arr2, 16);
	printf("%d ", ret);

	return 0;
}

结果是这样

感谢您的观看

最近更新

  1. TCP协议是安全的吗?

    2024-03-18 06:14:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-18 06:14:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-18 06:14:04       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-18 06:14:04       20 阅读

热门阅读

  1. 控制工程学 en 2

    2024-03-18 06:14:04       19 阅读
  2. ssh命令——安全远程连接服务

    2024-03-18 06:14:04       20 阅读
  3. 《C缺陷和陷阱》-笔记(5)

    2024-03-18 06:14:04       18 阅读
  4. 四级缓存实现

    2024-03-18 06:14:04       21 阅读
  5. IOS面试题object-c 149-152

    2024-03-18 06:14:04       16 阅读