四个内存函数

文章目录

  • memcpy函数(拷贝)
  • 模拟实现memcpy函数
  • memcpy的升级
  • memmove

之前的拷贝或赋值等都是对字符串操作的,而对内存中其它数据如结构体,数组中的数据的拷贝,都是要用内存函数来完成的。

memcpy函数(拷贝)

在这里插入图片描述
第一个参数为目标地址,第二个参数是源地址,第三个参数是要拷贝的字节大小。
这个函数拷贝相对于strcpy函数来说不仅限于对字符串的拷贝。

#include

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

模拟实现memcpy函数

#include 

void my_memcpy(void* dest, const void* src, size_t num)//为什么参数类型是void?
{
	while (num--)
	{
		*(char*)dest = *(char*)src;//为什么要强转为char指针类型?
		dest = (char*)dest + 1;//为什么(char*)dest++是错误的?
		src = (char*)src + 1;
	}
	
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1, 20);
	return 0;
}

以上模拟的memcpy当在拷贝自身数值时可能会出错
拷贝自身时有三种情况一种是源地址在目标地址的后面,一种是源地址和目标地址位置相同,一种是源地址在目标地址的前面
我们可以将它分为两种情况一种是源地址在目标地址前面时我们按照从前向后拷贝,一种是源地址在目标地址后面或相同时我们按照从后向前拷贝,为的是避免在拷贝过程中有的数据被覆盖掉。

memcpy的升级

#include 

void my_memcpy(void* dest, const void* src, size_t num)//为什么参数类型是void?
{
  void* ret = dest;
	if (src >= dest)
	{
		//从前向后拷贝
		while (num--)
		{
			*(char*)dest = *(char*)src;//为什么要强转为char指针类型?
			dest = (char*)dest + 1;//为什么(char*)dest++是错误的?
			src = (char*)src + 1;
		}
	}
	else
	{
		//从后向前拷贝
		while (num--)
		{
			/**(char*)dest + num = *(char*)src + num;*///这样写是错误的
			*((char*)dest + num) = *((char*)src + num);
		}
	}
  return ret;
}

不同编译器拷贝的结果不同,所以对自身进行拷贝时尽量使用memmove函数来进行拷贝

memmove

在这里插入图片描述

第一个参数为目标地址,第二个参数是源地址,第三个参数是要拷贝的字节大小。

memmove可以实现重叠内存的拷贝
#include

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

你可能感兴趣的:(C,c语言)