前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >memmove函数和memcpy函数的模拟实现

memmove函数和memcpy函数的模拟实现

作者头像
ahao
发布2024-03-19 18:48:36
500
发布2024-03-19 18:48:36
举报
文章被收录于专栏:学习学习

首先我们来了解memmove函数和memcpy函数的使用

memmove函数

他的函数所需参数如下 1.函数memcpy从source的位置开始向后复制num个字节的数据destination 指向的内存位置。 2.这个函数在遇到 ‘\0’ 的时候并不会停下来。 3.如果source和destination有任何的重叠,复制的结果都是未定义的

代码语言:javascript
复制
void * memcpy ( void * destination, const void * source, size_t num );

我们要注意,这里的num是以字节为单位的,而不是元素个数,并且由于这里我们不知道memmove所移动的内容是什么数据类型,所以移动的目的和源头都用void来定义,由于memmove函数还需有返回目的的起始地址,所以函数类型定义为void**。

下面我们就可以对memmove函数进行模拟实现 我们定义此模拟实现函数为my_memmove 我们定义数组

代码语言:javascript
复制
arr[]={1,2,3,4,5,6,7}

我们想要将数组中数字3,4,5放入1,2,3的位置中,也就是说src中的内容从前向后移动到det中,反之,如果采用从后向前将不会达到我们想要的下图的数组,移动后的数组内容如下图所示

我们将数组移动的内容进行分析,此时det在src的前面,我们可以先将数字3放入arr[0],然后一次放入4,5

下面来看另外一种情况,就是如果det在src的后面呢,该如何移动呢

这个时候我们就会发现从前向后的方法并不适用与这种情况了,我们可以采用从后向前的方式,若依旧采用从前向后的方式的话,会是这种效果

这个时候我们就可以开始构思函数了 由于函数最终需要返回det的起始地址,所以我们定义一个void* ret=det放入函数中,并且采用断言保证不为空指针

代码语言:javascript
复制
void my_memmove(void* det, void* src, size_t size)
{ 
        assert(det && src);
        void* ret = det;
}

接下来分析当det在src前面是的移动方式 由于不知道数据的类型,并且size的单位是字节,但是当数据的类型是int的时候,循环进行是该如何移动呢,我们就可以将det的指针类型强制转化为char*指针,就可以进行字节“++”操作了

代码语言:javascript
复制
if (det < src)//从前往后移动
	{
		int i = 0;
		for (i = 0; i < size; i++)
		{
			*(char*)det = *(char*)src;//强制类型转换
			arr1 = (char*)det + 1;
			arr2 = (char*)src + 1;
		}

反之,我们就写出det在src之后的部分

代码语言:javascript
复制
while (size--)
		{
			*((char*)det + size) = *((char*)src + size);
		}

到这里,memmove的模拟实现就完成了,我们还要记得返回ret,也就是det的起始地址 完整函数代码如下

代码语言:javascript
复制
void my_memmove(void* det, void* src, size_t size)
{
	assert(det && src);
	void* ret = det;
	if (det < src)//从前往后移动
	{
		int i = 0;
		for (i = 0; i < size; i++)
		{
			*(char*)det = *(char*)src;
			arr1 = (char*)det + 1;
			arr2 = (char*)src + 1;
		}
	} 
	else
	{
		while (size--)
		{
			*((char*)det + size) = *((char*)src + size);
		}
	}
	return ret;
}
memcpy函数

相对于memmove函数,memcpy的功能就没有怎么完整了,memmove和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的,所以,如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理。但是,有一些编译器的memcpy也可以处理重叠的的情况,就比如vs。 memcpy的模拟实现和memmove的差别不大 代码如下

代码语言:javascript
复制
void * memcpy ( void * det, const void * src, size_t size)
{
 void * ret = det;
assert(arr1 && arr2);
 while (size--) {
 *(char *)dst = *(char *)src;
 dst = (char *)dst + 1;
 src = (char *)src + 1;
 }
 return(ret);
}

大家可以发现,memcpy函数的模拟实现就是memmove函数模拟实现的一部分,就是只采用了从前向后的方式进行内存更改,所以这里我就不做过多的解释了,大家自行理解。

好了,今天的分享就到这里了!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • memmove函数
  • memcpy函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档