模拟内存拷贝函数:memcpy memmove_实现不定长数据拷贝函数,需要考虑地址重叠,(dest和sro butter的长度都大于等_sandmm112的博客-程序员宝宝

技术标签: C  c语言  memcpy  memmove  字节拷贝有无重叠  

1. 题目一:不使用库函数,模拟实现内存拷贝函数memcpy的功能。

分析:

memcpy与strcpy不同,它是以字节为单位进行拷贝,每次拷贝一个字节,使用时,需要了解要拷贝的字节数。同时,因为它是以字节进行拷贝,所以无类型限制,即对任意类型均可以使用,而strcpy专用于字符串。

它的拷贝原理与strcpy类似,strcpy以“\0”为结束判断依据,而memcpy以要拷贝的字节数为结束判断依据。

代码如下:


例一:将src拷贝到dest中,主函数代码:


运行结果:


例二:当希望将src中的后续字符依次前移时,希望得到“xjgqg”时,主函数变为如下:


运行结果:


显然,与我们预期一致。

例三:当希望将src中的字符依次后移时,希望得到“bbxjgq”时,主函数变为如下:

此时,运行结果为:


这显然与我们预期的结果不同。此时,memcpy的功能已经不再适用,这里就需要用到memmove。

2. 题目二:模拟实现内存拷贝函数memmove的功能

同样是内存拷贝函数,两者之间的区别是什么呢?

这里,我们分析下两个字符串拷贝的几种情况:src表示源字符串,dest表示目标字符串。(因为dest是目标字符串,所以dest的长度一定大于src的长度)

1)src的地址小于dest的地址,二者不重叠。

2)src的地址大于dest的地址,二者不重叠。

3)src的地址小于dest的地址,二者不重叠。

4)src的地址小于dest的地址,二者有重叠(包括src完全包含在dest中的情况)。

如下图:


在处理前无重叠情况时,memcpy是适用的。再由上述例二,例三知,情形三memcpy也是适用的,而memcpy不适用于情形四。

而memmove就是用于解决情形四的,更确切的说,它对这四种情形都适用。前三种情形可以用与memcoy相同的方法接解决,

那么,情形四如何解决呢?

分析:

首先,我们需要知道上述例三的结果是如何产生的,在就上图而言,当src向dest拷贝时,a先拷给d,b拷给e,c拷给f,当要将d拷给g时,发现原来的有效d已经被a替代,使之失效 ,所以结果会变为abcabca,与例三的的结果类似。

其次,知道了出错原因,如何解决呢,上述叙述中,是从左往右拷贝的,这里,我们需要从右往左拷贝,即先拷贝g,依次往左进行,即使后面的拷贝会覆盖g但g已经发挥起作用,已经失效,所以,可以从右往左拷。

然后,src,dest初始是在字符串开头,那么需要移到右边什么地方呢?这时,就要考虑需拷贝的字节数了,若需拷贝k个字节,则src,dest分别从src+k,dest+k开始,依次往左拷。

最后,我们考虑下情形四的条件,从图中,可以观察到,src<dest且src+strlen(src)>dest。而其余情形方法与memcpy相同。

通过分析,代码编写如下:


对上述例三进行验证:


运行结果:


可以看到,结果与预期一致。

注意:

在对字符串进行拷贝时,首选strcpy;

在对内存进行拷贝时,可以选取memmove和memcpy,

而memmove的功能是兼容memcpy的,在检测字符串是否重叠时,就可以选择memcpy。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sandmm112/article/details/79283372

智能推荐

Oracle数据库手工注入_oracle 手工注入_Stone_No1的博客-程序员宝宝

一、出现注入点的原因:程序员在编写代码时没有对用户输入的字符进行特殊处理。导致用户输入的特殊字符附带在参数中直接与数据库进行交互。二、注入过程1、打开一个连接地址:在网址后面加and 1=1 正常,and 1=2 错误。说明存在注入漏洞、2、判断一下数据库中的表and (select count(*) from admin)3、判断一下该网站有几个管理员。and

(四)在Android studio中 android-support-v4报错(已解决)_android studio support v4_AJ周的博客-程序员宝宝

在Android studio中 android-support-v4报错,其实是在Android studio中用的是的知识androidx.viewpager.widget.ViewPager代替了android-support-v4.ViewPager。。。等引用不用导入android-support-vXXX的包支持(!!!可能!!!是已经过时了)...

opencv打包成exe在win7运行报错_opencv-4.7.0-windows.exe_黑猫๑的博客-程序员宝宝

opencv打包成exe在win7运行报错1、安装过程错误警告opencv版本:3.4.3打包环境:win10运行环境:win7opencv报错:2、解决方案opencv插件打包提取码: fp7v将 api-ms-win-downlevel-shlwapi-l1-1-0.dll【System32】 放到 c:\windows\System32将api-ms-win-downlevel-shlwapi-l1-1-0.dll【SysWOW64】 放到C:\Windows\SysWOW64

2021-06-19 回文链表_Hello World......的博客-程序员宝宝

leetcode每日一题之回文链表题目链接:https://leetcode-cn.com/problems/palindrome-linked-list-lcci/submissions/题目描述:编写一个函数,检查输入的链表是否是回文的。示例 1:输入: 1-&gt;2输出: false 示例 2:输入: 1-&gt;2-&gt;2-&gt;1输出: true 解法1:自己的解法首先声明,本人的解法是通过了的。思想:首先遍历链表记录链表中的元素个数然后开辟一个数组,空间

uva103-Stacking_Boxes(dp最长递增子序列)_剑不飞的博客-程序员宝宝

Stacking Boxes BackgroundSome concepts in Mathematics and Computer Science are simple in one or two dimensions but become more complex when extended to arbitrary dimensions. Consider s

2 基于梯度的攻击——PGD_weixin_30379531的博客-程序员宝宝

PGD攻击原论文地址——https://arxiv.org/pdf/1706.06083.pdf1.PGD攻击的原理  PGD(Project Gradient Descent)攻击是一种迭代攻击,可以看作是FGSM的翻版——K-FGSM (K表示迭代的次数),大概的思路就是,FGSM是仅仅做一次迭代,走一大步,而PGD是做多次迭代,每次走一小步,每次迭代都会将扰动clip到规定范围内。...

随便推点

java中length和length()的区别_江湖偌大的博客-程序员宝宝

在java语言中String可以定义字符串变量,也可以定义字符串数组:length():用于求字符串变量的长度,即这个字符串有多少个字符;length:用于求字符串数组的长度,即这个数组有多少个字符串。1.字符串数组//Define an array of String.String[] strArray = { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"}; System.out

java8的lambda中的map相关操作_lamda合并 map entity_菠萝科技的博客-程序员宝宝

0 入门篇1 史上最简单入门:java8的lambda中的map相关操作:基础及注意事项图文详解2 java8的lambda中collect接口案例及原理详解,官方文档解读1 以下是正文本文为转载,原文链接:https://blog.csdn.net/w605283073/article/details/829871571. 介绍本入门教程将介绍Ja...

JavaScript中常用函数方法(对象篇)_js 对象 函数_YF-SOD的博客-程序员宝宝

目录Object(obj)object对象调用的方法object.hasOwnProperty(prop)object.isPrototypeOf(obj)object.propertyIsEnumerable(prop)Object上定义的静态方法Object.create(obj,propertiesObject)参数示例Object.getPrototypeOf(obj)Object.freeze(obj)Object.defineProperty(ob

sqlserver的登陆操作_sqlserver登录_pyhui2020的博客-程序员宝宝

找到sql server运行启动界面登陆界面使用 sql server身份验证老师的登陆密码 root123456成功登陆后

解决树莓派4B 3.5MM耳机接口没有声音的方法_树莓派4b 音频耳机_luhengs的博客-程序员宝宝

解决树莓派4B 3.5MM耳机接口没有声音的方法运行树莓派配置工具:sudo raspi-config一、选择1 System Options Configure system settin二、选择S2 Audio Select audio out through HDMI or 3.5mm jack三、在中Choose the audio output对话框中选择1 Headphones最后,选择Ok即可...

Ajax/JavaScript脚本大全,JS脚本大全_GoodShot的博客-程序员宝宝

栏目导航Java开源OPEN文档OPEN搜索OPEN家园OPEN资讯OPEN论坛AAccordionAutoCompleteAnimationCCalendarChartsCornersCropperCanvasCarouselColorDDragDropDatePickerDhtmlGoodiesDocumentationEEditorEffectsExtJsFFormsFrameworkGGa