memcpy使用+模拟实现

104 阅读2分钟

「这是我参与2022首次更文挑战的第21天,活动详情查看:2022首次更文挑战

内存函数

memcpy()-内存拷贝函数

image-20220209220933555

count:要拷贝的字节数

  • 函数memcpy从src位置开始向后赋值count个字节的数据到dest的内存位置,
  • 遇到 ‘\0’ 的时候不停下来
  • 如果source和destination有任何的重叠,复制的结果都是未定义的

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

模拟实现memcpy()

1.只知道要拷贝的字节数,不知道要拷贝的元素是什么类型。所以可以强转为char*指针->1个字节1个字节的拷贝


2.返回目标空间的起始地址,注意返回类型是void*,是指针,所以可以返回 若返回类型是void,则不可以返回,


3.目标空间不修改,所以可以使用const修饰


4.要拷贝的字节数不可能为负数,所以接收类型可以为无符号整数

void* my_memcpy(void* dest,const void* src,size_t count )
{
	assert(dest&&src);
	void* ret = dest;	//为了返回目标空间起始地址
	//共拷贝n个字节
	while(count--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;//这样写是防止编译器报错
		src = (char*)src + 1;
	}
	//若写成 dest = (char*)dest++; //有些编译器可能跑不过去
	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	my_memcpy(arr2, arr1, sizeof(int) * 10);
	int i = 0;
	for (i = 0;i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

注意:我们这种模拟实现的方法,不能处理重叠的内存拷贝,

如:想要将数组的1234拷贝到3456中,

void* my_memcpy(void* dest, const void* src, size_t count)
{
	assert(dest && src);
	void* ret = dest;	//为了返回目标空间起始地址
	//共拷贝n个字节
	while (count--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;//这样写是防止编译器报错
		src = (char*)src + 1;
	}
	//若写成 dest = (char*)dest++; //有些编译器可能跑不过去
	return ret;
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memcpy(arr+2, arr, 16);
	int i = 0;
	for (i = 0;i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

想要的效果:1212347890

使用my_memcpy得到的结果:1 2 1 2 1 2 7 8 9 10

原因:

image-20220209221313117

但是使用库函数memcpy函数,可以实现拷贝

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

打印结果:1 2 1 2 3 4 7 8 9 10


但是C语言只要求memcpy函数可以实现不重叠的内存拷贝即可,要实现重叠内存拷贝的话,实现memmove函数