文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C语言模拟实现memmove的示例代码

2022-12-29 18:00

关注

前言

上一篇我们介绍了memcpy和strcpy的区别,以及memcpy模拟实现,但这两个库函数都有一个缺点,那就是不能自己复制自己的内容

例子

这有一个数组arr,其元素分别为1、2、3、4、5、6、7、8、9、10,我们想将1、2、3、4复制到2的后面,从而将数组arr变成1、2、1、2、3、4、7、8、9、10

用memcpy尝试

我们发现,跟我们预期的 1、2、1、2、3、4、7、8、9、10有出入。

错误原因

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(arr + 2, arr, 16);

memcpy实现过程

void* my_memcpy(void* dest, void* src, size_t count)
{
    void* ret = dest;
    while (count--)
    {
        *(char*)dest = *(char*)src;
        dest = (char*)dest + 1;
        src = (char*)src + 1;
    }
    return ret;
} 

当我们这样操作时,src一开始指向1,1被复制到了3的位置上,后面指向2,2被复制到4的位置上,当src指针指向原来的3时,指向的内容变成了1,又将1复制到了5的位置上,当src指向原来的4时,指向的内容变成了2,又将2复制到了6的位置上。所以就出错了。

用memmove尝试

我们发现目的达到了,说明memmove适用于内存发生重叠的情况。那么memmove是怎么实现的呢?

memmove的模拟实现

整段代码

void* my_memmove(void* dest, void* src, size_t count)
{
	void* ret = dest;
	if (dest < src)
	{
		while (count--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		while (count--)
		{
			*((char*)dest + count) = *((char*)src + count);
		}
	}
	return ret;
}

memmove的定义

由图可知,memmove的返回值是目标地址,形势参数分别是(目标地址,源头地址,需要操作的字节数)

具体实现步骤

第一种情况(dest在src后),采用由后向前复制

由上面的错误分析,我们知道是因为后面要被复制过去的内容被更改了,还是用上面的例子做示范,我们从1开始复制的话,1会将3覆盖掉,进而导致想将3复制到到5的位置上时,实际上是将1复制到5的位置上。

那么我们如果从4开始复制呢?我们由后至前进行复制,将4复制到6,再将3复制到5,这样我们就不怕3、4被1、2覆盖掉了。

我们要想先将4复制到6,先得将src指向4,dest指向6,然后再进行交换。我们用加传过去的字节数来实现。

*((char*)dest + count) = *((char*)src + count);

我们想将指针前移,直接count减一就行,又因为我们要重复这一行为,所以我们使用while循环来实现。

        while (count--)
		{
			*((char*)dest + count) = *((char*)src + count);
		}

第二种情况(dest在src前),采用由前向后复制

如果dest在src前,我们还能用由后至前的方法复制吗?

例如,我们将3、4、5、6向前移动2次,也就是将1、2、3、4、5、6、7、8、9、10变成3、4、5、6、5、6、7、8、9、10

我们发现并没有成为我们想象当中的样子。

错误原因

依然是要被复制的内容在被复制之前就被更改了,这里先将6移动到4,5移动到3,想将4移动到2时,实际上复制过去的是6,以此类推...

所以我们要采用由前向后复制的方法(【C语言】字符串拷贝函数(strcpy)与内存拷贝函数的不同及内存拷贝函数(memcpy)的模拟实现一文里有)

总结

memcpy不能实现自己拷贝自己,也就是不适用于内存叠加的情况。我们用memmove便可以解决这个问题。

对于memmove的模拟实现,核心思想就是将会被覆盖的、要被复制的内容提前使用。这里分为两种情况,一种是被复制的内容地址在目标内容地址的前面,另一种就是被复制的内容地址在目标内容地址的后面,对于前一种情况,我们使用由后至前进行复制的方法,对于后一种情况,我们使用由前至后进行复制的方法(dest在src后就由后向前。dest在src前,就由前向后)。

到此这篇关于C语言模拟实现memmove的示例代码的文章就介绍到这了,更多相关C语言 memmove内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯