C语言->内存函数详解

memcpy

概念与使用

  • 实现这个函数之前我们先认识一下这个函数
void * memcpy ( void * destination, const void * source, size_t num );
  • 这个函数的作用就是将source后的num个字节的数据保存到destination的内存位置
  • 注意:destination和source是不可以出现重叠的

具体实现的例子:

#include<stdio.h>

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

在这里插入图片描述

  • 由上面可以看到我们使用memcpy函数将arr1(source)的内容保存到了arr2(destination)的位置,因为num是8数组元素的类型是int,所以只有前俩个元素被替换

自主模拟实现(my_memcpy)

思路:
1.函数传参的三个值分别为目的地地值,源头地址和想要复制到目的地的元素的字节数(这里注意是字节数),所以传参时形参类型分别为(void*,void*,size_t)

(void*)是因为不知道传过来的是什么类型的指针所以用void*来接收比较合适
size_t是为了确保传过来的数不是负数

2.根据函数相关概念我们可以了解到函数的返回值是void*
3.了解到函数可以直接将源头的数据复制到目的地,还可以规定复制的字节数,所以这里我们可以用while循环来解决,循环条件为(num–)这样等想要的字节数复制完了以后循环自然而然就停止了
4.想到(void*)是不能被解引用的,那么用什么比较合适呢,既然我们要实现的函数是一个字节一个字节替换,那么用(char*)就比较合适
接下来是函数实现案例:

void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);//断言防止传来的指针为空指针
	void* ret = dest;//将dest的起始位置付给ret
	while (num--)
	{
		*(char*)dest = *(char*)src;//将第一个字节的内容复制给dest
		dest = (char*)dest + 1;//指针位置加一指向下一个字节
		src = (char*)src + 1;
	}

	return ret;
}

memmove

概念与使用

  • 同样我们先认识一下这个函数
void * memmove ( void * destination, const void * source, size_t num );
  • 这个函数和上一个函数的区别就在于memmove处理的源和目标是可以重叠的
    例子:
int main()
{
	int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	
	memmove(arr1 + 2, arr1, 8);

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

在这里插入图片描述

  • 由上面我们可以看到函数将1,2复制到了3,4的位置上,这就说明了memmove允许在源和目标重叠的情况下进行和memcoy一样的操作

自主模拟实现(my_memmove)

思路与上面不同的是我们要解决重叠时还可以进行复制的功能

  • 我们可以想到如果这时还用上一个函数的方法是不能达到目的的,如果dest在src前面(dest的地址相较于src更低),当我们从前向后并不能达到目的,这时我们就不得不考虑一下换个方法,从后往前就比较适合,不会出现想要替换的数被覆盖的情况

  • 根据上面我们能分析出,当dest<src时用从前往后的方法,其余情况就用从后往前,这样就解决了被覆盖的问题

  • 代码如下:

void* my_memove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	if (src > dest)
	{
		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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值