C进阶_内存库函数_和这群虫豸在一起,怎能搞好政治呢?

文章详细介绍了memcpy和memmove两个C语言中的内存操作函数。memcpy用于不重叠的内存区域复制,而memmove则能处理重叠区域。文章通过示例和模拟实现指出了memcpy在处理重叠内存时的问题,并提供了改进的memmove实现方式。
摘要由CSDN通过智能技术生成

其实之前我写过这篇……但是不够详细!今天重新写一下。

目录

memcpy

模拟实现memcpy

memmove

模拟实现memmove


memcpy

它的函数原型是:

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

查阅文档它的文档:

Copy block of memory

Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.

The underlying type of the objects pointed to by both the source and destination pointers are irrelevant for this function; The result is a binary copy of the data.

The function does not check for any terminating null character in source - it always copies exactly num bytes.

To avoid overflows, the size of the arrays pointed to by both the destination and source parameters, shall be at least num bytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).

可以知道它的作用是从source的位置开始向后复制num个字节的数据到destination的内存位置。

它遇到'\0'的时候并不会停下来,不会对停止字符做检查。

如果source和destination有任何的重叠,复制的结果都是未定义的。

请看示例:

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

这是将arr1中的前五个元素给arr2。

为什么memcpy参数最后是20呢?

这是因为memcpy是内存拷贝,参数代表拷贝的字节数。

而int型是4个字节,要拷贝arr1中前五个元素给arr2,参数就为4*5=20。

运行结果如下:

模拟实现memcpy

#include <assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	//前->后
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

但是……有虫豸(Bug)!

和这群虫豸在一起,怎能搞好政治呢?

 一旦dest和src有重叠的部分,虫豸就产生了!

注意看,绿色方框是src,紫色方框是dest。

在拷贝时,会一个一个地将src的字符拷贝给dest。

如果是从前往后拷贝:

1到了原来3的位置,2到了原来4的位置,在这时3和4都已经没有了,那么5就成了1,6就成了2,7就成了1。

所以当函数调用完,dest里不是12345而是12121。

还有一种情况是从后往前拷贝:

5到了原来7的位置,4到了原来6的位置,3到了原来5的位置,2到了原来4的位置,1到了原来3的位置。这就不会出错!

如果src在dest之前,那就要从后往前拷贝。

同理,如果src在dest之后,就要从前往后拷贝。

总结下,dest的位置在第一个区域就要从前往后拷贝,在第二个区域就要从后往前拷贝,在第三个区域的话,从前往后拷贝和从后往前拷贝皆可~

那么该怎么实现这些功能,进而杀死虫豸?当然要请昆虫学家金载圭了!

memmove

它的函数原型如下:

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

请看文档:

Move block of memory

Copies the values of num bytes from the location pointed by source to the memory block pointed by destination. Copying takes place as if an intermediate buffer were used, allowing the destination and source to overlap.

The underlying type of the objects pointed by both the source and destination pointers are irrelevant for this function; The result is a binary copy of the data.

The function does not check for any terminating null character in source - it always copies exactly num bytes.

To avoid overflows, the size of the arrays pointed by both the destination and source parameters, shall be at least num bytes.

和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

如果源空间和目标空间出现重叠,就得使用memmove函数处理。

模拟实现memmove

void* my_memmove(void* dest, const void*src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值