C 语言 【模拟实现内存库函数】

 1、memcpy

        memcpy函数是C/C++语言中的一个用于内存复制的函数,声明在 string.h 中(C++是 cstring)。其原型是:

void * memcpy ( void * destination, const void * source, size_t num );

        其中,destination表示的是要拷贝到的目标起始地址,source表示要拷贝内容的起始地址,num表示要拷贝的字节数。函数的作用为:将 num个bytes 的值从 source 指向的位置直接复制到destination 指向的内存块。  

        模拟实现:我们可以看到,destination和source指针的类型均为void*类型,也就是说传入的指针变量不知道它的具体类型。这其实很容易理解,在对内存块进行拷贝的时候,由于情况很多,比如:这次需要拷贝整型内容,下次需要拷贝字符型内容,过几天又需要拷贝结构体类型的内容,所以在函数设计的时候要增大函数的普适性,在这里的指针类型就使用void*类型来接收指针。

        函数的第三个参数是num,它表示要拷贝的字节数量,内存块的最小单位为字节正好与之对应大小的数据类型为char类型。所以我们不考虑具体操作的原数据是什么类型,即不需要考虑原来数据占有几个字节,我们将这些数据全部拆成一个个独立的字节数据进行搬移。那么在使用指针的时候只需要将其强制类型转换成char*类型进行循环赋值即可。下面是函数的实现:

void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);size_t i = 0;void* ret = dest;for (i = 0; i < num; i++)//每次搬移一个字节{*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}

        在指针加一的时候进行要注意,不能直接写成(char*)dest++,这是因为(char*)dest是临时的在进行++操作的时候,dest依旧是void*类型。让我们来测试一下

#include <stdio.h>int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int sz1 = sizeof(arr1) / sizeof(arr1[0]);int arr2[10] = 0;my_memcpy(arr2, arr1, sizeof(int) * 3);//拷贝三个数字int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}

        运行结果: 

        上述的函数已经能实现绝大多数的内存拷贝问题,但是存在一种可能程序可能会报错,假设源地址内存块 与 目标地址内存块发生重叠,再拷贝的过程中会破坏掉源地址内存块的数据,导致后面的拷贝发生拷贝的是错误的数据。画个图来看一下具体问题:

        发生错误的原因就是在拷贝过程中对源地址空间的数据进行了破坏,这种破坏是算法导致的,可以改变策略来应对这种问题。我们可以看到上面算法拷贝的顺序从源地址空间的起始向源地址空间的末尾进行拷贝,那我们 可以改变拷贝的顺序,从右向左拷贝:

        还会有一种情况,交叠的部分在src的左侧时我们采取的策略依然是从左到右的拷贝顺序:

        其实,做出这些策略的调整的核心思想就是:源地址空间的数据在拷贝过程中不能被破坏。

下面让我们重新审视这个问题进行总结,我们将dest空间看成一个运动的方框,src空间是静止不动的。 当dest<src时拷贝的顺序为从左往右,当dest>src时从右往左进行拷贝。一般在处理这种有交集的问题时,我们使用的是memmove函数。

2、memmove

        有了在memcpy中的过渡部分,我们来模拟实现一下memmove。代码如下:

#include <assert.h>void* my_memmove(void* dest, const void* src, size_t num)
{assert(dest && src);size_t i = 0;void* ret = dest;int temp = num;for (i = 0; i < num; i++){if (dest < src){//从左往右拷贝*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}else{//从右往左拷贝*((char*)dest+ temp -1)=*((char*)src + temp - 1);temp--;}}return ret;
}

        所谓的从左往右这个方向指的是 从src的左边还是右边开始拷贝。

3、两者的区别

        他们的作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。

        

        

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【大数据学习 | flume】flume的概述与组件的介绍

1. flume概述 Flume是cloudera(CDH版本的hadoop) 开发的一个分布式、可靠、高可用的海量日志收集系统。它将各个服务器中的数据收集起来并送到指定的地方去&#xff0c;比如说送到HDFS、Hbase&#xff0c;简单来说flume就是收集日志的。 Flume两个版本区别&#xff1a; ​ 1&…

01:(手撸HAL+CubeMX)时钟篇

&#xff08;手撸HALCubeMX&#xff09;时钟篇 1、对SystemInit函数的分析2、使用HSI将总线时钟配置为最高频率3、使用HSE将总线时钟配置为最高频率4、使用Cube配置时钟树的参数5、对HAL_Init函数分析6、对系统定时器中断服务函数分析 有关时钟树和上电/复位的基础知识请参考“…

大数据新视界 -- 大数据大厂之 Impala 存储格式转换:从原理到实践,开启大数据性能优化星际之旅(下)(20/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Spring Boot实现文件上传与OSS集成:从基础到应用

目录 前言1. 文件上传的基础实现1.1 前端文件上传请求1.2 后端文件接收与保存 2. 集成第三方OSS服务2.1 准备工作2.2 编写OSS集成代码2.3 修改Controller实现文件上传至OSS 3. 文件上传的扩展&#xff1a;多文件上传与权限控制结语 前言 随着互联网应用的快速发展&#xff0c;…

微服务各组件整合

nacos 第一步&#xff0c;引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency> 第二步&#xff0c;增加配置 spring:application:name: …

机器学习总结

机器学习按照模型类型分为监督学习模型&#xff0c;无监督学习模型和概率模型三大类&#xff1a; 下图是机器学习笔记思维导图&#xff0c;&#xff1a; 一.什么是机器学习 从本质上讲&#xff0c;可以认为机器学习就是在数据中寻找一种合适的函数来描述输入与输出之间的关系。…

WEB攻防-通用漏洞SQL注入sqlmapOracleMongodbDB2等

SQL注入课程体系&#xff1a; 1、数据库注入-access mysql mssql oracle mongodb postgresql 2、数据类型注入-数字型 字符型 搜索型 加密型&#xff08;base64 json等&#xff09; 3、提交方式注入-get post cookie http头等 4、查询方式注入-查询 增加 删除 更新 堆叠等 …

三、损失函数

损失函数 前言一、分类问题的损失函数1.1 二分类损失函数1.1.1 数学定义1.1.2 函数解释&#xff1a;1.1.3 性质1.1.4 计算演示1.1.5 代码演示 1.2 多分类损失函数1.1.1 数学定义1.1.2 性质与特点1.1.3 计算演示1.1.4 代码演示 二、回归问题的损失函数2.1 MAE损失2.2 MSE损失2.3…

PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸

小编最近有一篇png图片要批量压缩&#xff0c;大小都在5MB之上&#xff0c;在网上找了半天要么就是有广告&#xff0c;要么就是有毒&#xff0c;要么就是功能复杂&#xff0c;整的我心烦意乱。 于是我自己用python写了一个纯净工具&#xff0c;只能压缩png图片&#xff0c;没任…

测试工程师简历「精选篇」

【#测试工程师简历#】一份专业且引人注目的测试工程师简历&#xff0c;无疑是你敲开理想职位大门的金钥匙。那么&#xff0c;如何撰写一份既体现技术水平又彰显个人特色的简历呢&#xff1f;以下是幻主简历网整理的测试工程师简历「程序员篇」&#xff0c;欢迎大家阅读收藏&…

git下载慢下载不了?Git国内国外下载地址镜像,git安装视频教程

git安装下载的视频教程在这 3分钟完成git下载和安装&#xff0c;git国内外下载地址镜像&#xff0c;Windows为例_哔哩哔哩_bilibili 一、Git安装包国内和国外下载地址镜像 1.1国外官方下载地址 打开Git的官方网站&#xff1a;Git官网下载页面。在页面上选择对应的系统&…

专题十八_动态规划_斐波那契数列模型_路径问题_算法专题详细总结

目录 动态规划 动态规范五步走&#xff1a; 1. 第 N 个泰波那契数&#xff08;easy&#xff09; 解析&#xff1a; 1.状态表达式&#xff1a; 2.状态转移方程&#xff1a; 3.初始化&#xff1a; 4.填表顺序&#xff1a; 5.返回值 编写代码&#xff1a; 总结&#xff…

阿里云centos7.9服务器磁盘挂载,切换服务路径

项目背景 1、项目使用的服务器为阿里云centos7.9&#xff0c;默认的磁盘为vda&#xff0c;文件系统挂载在这个磁盘上&#xff0c;项目上使用的文件夹为/home/hnst/uploadPath 2、vda使用率已达到91% 3、现购置一块新的磁盘为vdb&#xff0c;大小为2T 目的 切换服务所使用的…

STM32问题集

这里写目录标题 一、烧录1、 Can not connect to target!【ST-LINK烧录】 一、烧录 1、 Can not connect to target!【ST-LINK烧录】 烧录突然 If the target is in low power mode, please enable “Debug in Low Power mode” option from Target->settings menu 然后就&…

Scala学习记录,case class,迭代器

case class case class创建的对象的属性是不可改的 创建对象&#xff0c;可以不用写new 自动重写&#xff1a;toString, equals, hashCode, copy 自动重写方法&#xff1a;toString,equals,hashCode,copy 小习一下 1.case class 的定义语法是什么 基本形式&#xff1a;case …

成都睿明智科技有限公司解锁抖音电商新玩法

在这个短视频风起云涌的时代&#xff0c;抖音电商以其独特的魅力迅速崛起&#xff0c;成为众多商家争夺的流量高地。而在这片充满机遇与挑战的蓝海中&#xff0c;成都睿明智科技有限公司犹如一颗璀璨的新星&#xff0c;以其专业的抖音电商服务&#xff0c;助力无数品牌实现从零…

阅读2020-2023年《国外军用无人机装备技术发展综述》笔记_技术趋势

目录 文献基本信息 序言 1 发展概况 2 重点技术发展 2.1 人工智能技术 2.1.1 应用深化 2.1.2 作战效能提升 2.2 航空技术 2.2.1螺旋桨设计创新 2.2.2 发射回收技术进步 2.3 其他相关技术 2.3.1 远程控制技术探 2.3.2 云地控制平台应用 3 装备系统进展 3.1 无人作…

LeetCode 86.分隔链表

题目&#xff1a; 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初始相对位置。 思路&#xff1a; 代码&#xff1a; /*** Definiti…

SystemVerilog学习笔记(六):控制流

条件语句 条件语句用于检查块中的语句是否被执行。条件语句创建语句块。如果给出的表达式是 true&#xff0c;执行块中的语句集&#xff0c;如果表达式为 false&#xff0c;则 else 块语句将最后执行。 序号条件语句1.if2.if-else3.if-else ladder4.unique if5.unique0 if6.p…

SQL,力扣题目1127, 用户购买平台

一、力扣链接 LeetCode_1127 二、题目描述 支出表: Spending ---------------------- | Column Name | Type | ---------------------- | user_id | int | | spend_date | date | | platform | enum | | amount | int | ------------------…