内存函数 memcpy 和 memmove 的讲解和模拟实现

目录

一.什么是 memcpy 函数

模拟思路

代码实现 

二.什么是 memmove 函数

模拟思路

代码实现


一.什么是 memcpy 函数

我们打开 cplusplus 官网查看:

memcpy - C++ Reference (cplusplus.com)

官方文本显示:

内存复制块

  • 将 num 字节的值从源指向的位置直接复制到目标指向的内存块
  • 源指针和目标指针所指向的对象的底层类型与此函数无关;结果是数据的二进制副本
  • 该函数不检查源中是否有任何终止null字符——它总是精确地复制num个字节
  • 为了避免溢出,目标参数和源参数所指向的数组的大小应该至少为 num 字节,并且不应该重叠(对于重叠的内存块,memmove 是一种更安全的方法)

上述文本可能不够直观,我们使用官方提供的例子观察他的具体作用:

/* memcpy example */
#include <stdio.h>
#include <string.h>struct 
{char name[40];int age;
} person, person_copy;int main()
{char myname[] = "Pierre de Fermat";/* using memcpy to copy string: */memcpy(person.name, myname, strlen(myname) + 1);person.age = 46;/* using memcpy to copy structure: */memcpy(&person_copy, &person, sizeof(person));printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);return 0;
}

 输出结果:

        结合代码和输出结果来看,我们申明了俩个结构体,并且我们手动给结构体 person 的俩个变量进行了赋值,而结构体 person_copy 我们并没有对其初始化赋值,我们使用了 memcpy 函数将结构体 person 中的值复制给了结构体 person_copy ,然后我们打印输出 person_copy 中的变量的值,发现我们确实是拿到了这俩个值

模拟思路

当我们拿到一个字符串后,首先要确定复制的起点位置和复制目标的起点位置

 

然后逐一复制字节

 

代码实现 

        在这里,我们使用 void* 的指针来拿到各种数据类型的地址,然后强制转化为 char* 方便我们对单个字节进行访问(字符型指针解引用只能访问一个字节),函数参数方面,只需要拿到俩个地址加上需要复制多少个字节的大小的值就可以了

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

二.什么是 memmove 函数

我们打开 cplusplus 官网查看:

memmove - C++ Reference (cplusplus.com)

 

官方文本显示:

移动内存块

  • 将 num 字节的值从源指向的位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样进行,从而允许目标和源重叠
  • 源指针和目标指针所指向的对象的底层类型与此函数无关;结果是数据的二进制副本
  • 该函数不检查源中是否有任何终止 null 字符——它总是精确地复制 num 个字节
  • 为了避免溢出,目的参数和源参数所指向的数组的大小至少为 num 字节

上述文本可能不够直观,我们使用官方提供的例子观察他的具体作用:

 

/* memmove example */
#include <stdio.h>
#include <string.h>int main ()
{char str[] = "memmove can be very useful......";memmove (str+20,str+15,11);puts (str);return 0;
}

输出结果:

        我们可以看见,原本的字符串是 memmove can be very useful...... 但是输出的却是 memmove can be very useful. 也就是我们将后半部分的 very useful 往后移动了一段距离

模拟思路

        在模拟实现这个功能之前,有一点值得注意,相较于之前的 memcpy 函数,这里的 memmove 函数在移动的时候,内部是有重复部分的,如果还是按照上面那种方法实现的话,会出现数据反复覆盖导致丢弃了真实数据的情况,如图所示

对于这个情况,我们换一个交换字节的顺序就可以解决,如图

        也就是说,我们只需要做出合理的判断,选择正确的顺序,就可以实现功能,根据我们的经验,如果我们要实现的是从前往后移动拷贝的话,那我们就从后往前访问,反之,如果我们要从后往前移动拷贝的话,那我们就从前往后访问

代码实现

void* my_memmove(void* dest, const void* src, size_t sz)
{assert(dest && src);void* ret = dest;if (dest < src){//前->后int i = 0;for (i = 0; i < sz; i++){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else{//后->前while (sz--){*((char*)dest+sz) = *((char*)src + sz);}}return ret;
}

本次分享就到此为止了,如有错误欢迎积极指出,希望我的分享能给您带来帮助

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/140039.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

去耦电路设计应用指南(一)MCU去耦设计介绍

&#xff08;一&#xff09;MCU去耦设计介绍 1. 概述2. MCU需要去耦的原因2.1 去耦电路简介2.2 电源噪声产生的原因2.3 插入损耗2.4 去耦电路简介 参考资料来自网上&#xff1a; 1. 概述 我们经常看到单片机或者IC电路管脚常常会放置一个或者多个陶瓷电容&#xff0c;他们主要…

安防监控视频云存储平台EasyNVR对接EasyNVS时,一直不上线该如何解决?

视频安防监控平台EasyNVR可支持设备通过RTSP/Onvif协议接入&#xff0c;并能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等多种格式。 近期有用户在使用安防视频平台EasyNVR对接上级平台EasyNVS时&#xff0c;出现了一直不上线…

mysql事务测试

mysql的事务处理主要有两种方法1、用begin,rollback,commit来实现 begin; -- 开始一个事务 rollback; -- 事务回滚 commit; -- 事务提交 2、直接用set来改变mysql的自动提交模式 mysql默认是自动提交的&#xff0c;也就是你提交一个sql&#xff0c;它就直接执行&#xff01;我…

Windows 基于Visual Studio 开发Qt 6 注意事项

前提条件&#xff1a; 1、Visual Studio 2022 社区版(免费版) 2、Qt-6.5.1版本 Qt Vistual Studio Tools下载 先打开Visual Studio 2022 社区版 &#xff1a; 点击扩展-》管理拓展按钮后&#xff0c;在搜索框中输入Qt&#xff0c;点击这里第一个扩展安装。 Qt Visual Stud…

计算机毕设 图像识别-人脸识别与疲劳检测 - python opencv

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.2 打哈欠检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业…

云计算战略:选择适合你业务的云平台

文章目录 云计算的概述选择云平台的关键因素1. 业务需求2. 预算3. 性能要求4. 数据隐私和合规性 示例&#xff1a;选择适合的云平台业务需求预算性能要求数据隐私和合规性 代码示例&#xff1a;使用云平台服务结论 &#x1f389;欢迎来到云计算技术应用专栏~云计算战略&#xf…

Linux下ThinkPHP5实现定时器任务 - 结合crontab

实例一&#xff1a; 1.在/application/command创建要配置的PHP类文件&#xff0c;需要继承Command类&#xff0c;并重写configure和execute两个方法&#xff0c;例如: <?php namespace app\command; use think\console\Command; use think\console\Input; use think\cons…

uvm源码解读-sequence,sequencer,driver三者之间的握手关系1

1.start item 1.start_item();sequencer.wait_for_grant(prior);this.pre_do(1);需要指出&#xff0c;这里明确说明了wait_for_grant和send_request之间不能有任何延迟&#xff0c;所以在mid_do这个任务里千万不能有任何延迟。 task uvm_sequencer_base::wait_for_grant(uvm…

OpenCV实现图像边缘检测(sobel算子、laplacian算子、Canny边缘检测)

边缘检测原理 1&#xff0c;Sobel算子 1.1代码实现 import cv2 as cv import numpy as np import matplotlib.pyplot as plt from pylab import mplmpl.rcParams[font.sans-serif] [SimHei]img cv.imread("lena.png",0)#计算sobel卷积结果 x cv.Sobel(img,cv.CV_…

MySQL数据库详解 二:数据库的高级语言和操作

文章目录 1. 克隆表 ---- 将数据表的数据记录生成到新的表中1.1 方式一&#xff1a;先创建新表&#xff0c;再导入数据1.2方式二&#xff1a;创建的时候同时导入 2. 清空表 ---- 删除表内的所有数据2.1 delete删除2.2 truncate删除&#xff08;重新记录&#xff09;2.3 创建临时…

【刷题篇】回溯算法(深度优先搜索(一))

文章目录 无重复字符串的排列组合员工的重要性图像渲染被围绕的区域 无重复字符串的排列组合 无重复字符串的排列组合。编写一种方法&#xff0c;计算某字符串的所有排列组合&#xff0c;字符串每个字符均不相同。 class Solution { public:void DFS(string &s,vector<s…

记一次失败的pip使用经历

python如何使用pip工具下载第三方库&#xff1f; 首先&#xff0c;安装并配置好python和pip的环境&#xff0c;特别注意pip放在python的script文件下&#xff0c;有pip和pip3两种&#xff0c;选择pip3版本。如下图所示。 然后打开命令行窗口&#xff0c;检查python和pip工具是…

Android之MediaCodec::PostAndAwaitResponse消息原理(四十三)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

Python异步编程并发执行爬虫任务,用回调函数解析响应

一、问题&#xff1a;当发送API请求&#xff0c;读写数据库任务较重时&#xff0c;程序运行效率急剧下降。 异步技术是Python编程中对提升性能非常重要的一项技术。在实际应用&#xff0c;经常面临对外发送网络请求&#xff0c;调用外部接口&#xff0c;或者不断更新数据库或文…

Vue 的组件加载顺序和渲染顺序

1、结论先行 组件的加载顺序是自上而下的&#xff0c;也就是先加载父组件&#xff0c;再递归地加载其所有的子组件。 而组件渲染顺序是按照深度优先遍历的方式&#xff0c;也就是先渲染最深层的子组件&#xff0c;再依次向上渲染其父组件。 2、案例 下面是一个简单的示例代…

Ingress Controller

什么是 Ingress Controller &#xff1f; 在云原生生态中&#xff0c;通常来讲&#xff0c;入口控制器( Ingress Controller )是 Kubernetes 中的一个关键组件&#xff0c;用于管理入口资源对象。 Ingress 资源对象用于定义来自外网的 HTTP 和 HTTPS 规则&#xff0c;以控制进…

【C语言】字符函数和字符串函数(含模拟)

前言&#xff1a; 在做OJ题或阅读代码时或多或少会遇到一些字符函数和字符串函数&#xff0c; 如果不认识或不熟悉就会造成不便&#xff0c; 本篇文章主要是为了这方面而存在&#xff0c; 此篇介绍各个字符串的功能与使用方法&#xff0c; 下一篇会讲解如何模拟这些函数 重点&a…

Java Fluent编程

背景 Fluent Api最早是由Martin Fowler1提出的一种简洁的编程风格, 其每一步的执行都返回一个对象并可用于进一步的方法调用. 这样的编程风格可以很好的简化某些领域的开发, 并显著地提高代码的可读性和可维护性. 无论是在Java的流式api中, 还是众多DLS中都有它的身影. 原因主…

备受以太坊基金会青睐的 Hexlink,构建亿级用户涌入 Web3的入口

早在 2021 年 9 月&#xff0c;以太坊创始人 Vitalik Buterin 就曾提出了 EIP-4337&#xff08;账户抽象&#xff09;提案&#xff0c;并在去年 10 月对该提案进一步更新&#xff0c;引发行业的进一步关注。在今年 3 月&#xff0c;EIP-4337 提案正式通过审计&#xff0c;并成为…

SpringBean的生命周期

SpringBean的生命周期 SperingBean的生命周期是从Bean实例化之后&#xff0c;即通过反射创建出对象之后&#xff0c;到Bean成为一个完整对象&#xff0c;最终存储到单例池中&#xff0c;这个过程被称为Spring Bean的生命周期。Spring Bean的生命周期大体上分为三个阶段 Bean的…