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

本篇文章目录

  • 相关文章
  • 1. 模拟 memcpy 内存拷贝
  • 2. 模拟 memmove 内存移动

相关文章

  1. 【C语言】数据在内存中是以什么顺序存储的?
  2. 【C语言】整数在内存中如何存储?又是如何进行计算使用的?
  3. 【C语言】利用void*进行泛型编程
  4. 【C语言】4.指针类型部分

使用内存库函数实际上要包含string.h头文件,这个大伙要注意。

1. 模拟 memcpy 内存拷贝

两个指针的指向必须是两块互相独立的内存区域,即两个不同的数组。
dest空间必须比src空间大;
bytes表示要从src拷贝到dest的字节数。

// void* 通用的泛型编程,可以接收任何指针
void* my_memcpy(void* dest, const void* src, size_t bytes) {assert(dest && src);if (dest == src) {return dest;}void* t = dest;while (bytes--) {// 不清楚void*接收的是什么类型指针,直接char*一个个字节拷贝。*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;/*((char*)dest)++;((char*)src)++;---------------++((char*)dest);++((char*)src);这两种写法换成c++都不行*/}return t;
}
int main() {int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8 };int arr2[] = { 1, 2, 3, 4};my_memcpy(arr1 + 4, arr2, sizeof(int) * 4);for (int i = 0; i < 8; i++) {printf("%d ", arr1[i]);}return 0;
}

在这里插入图片描述

对于标准的memcpy,如果不进行完善实际上是有问题的:假设有一个数组 int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 },指针dest和指针src两个指针指向同一个数组内存,并且以字节为单位进行内存移动,会出现几种情况:

1.dest和src指向同一个地址,如my_memcpy(arr, arr, 4),等于啥也没动;2.dest指向地址值大于src2.1 如my_memcpy(arr + 4, arr, 16),也就是将5 6 7 8改成1 2 3 4,结果为1 2 3 4 1 2 3 4;-----------------------------------------------------2.2 如my_memcpy(arr + 2, arr, 16),也就是将3 4 5 6改成1 2 3 4,即 1 2 1 2 3 4 7 8但结果会变成1 2 1 2 1 2 7 8,因为原来3 4位置被改成了1 2。3.dest指向地址值小于src3.1 如my_memcpy(arr, arr + 4, 16),也就是将1 2 3 4改成5 6 7 8,结果为5 6 7 8 5 6 7 8;-----------------------------------------------------3.2 如my_memcpy(arr, arr + 2, 16),也就是将1 2 3 4改成3 4 5 6,结果为 3 4 5 6 5 6 7 8。

到这里会发现,也就只有2.2的结果不是我们想要的,这是因为自己实现的memcpy并不不完善,如果是string.h库函数中的memcpy则不存在这个问题。
在这里插入图片描述
本来是要将3 4 5 6改成1 2 3 4,结果改成了1 2 1 2。

事实上对于memcpy函数,C语言标准定义的是两个指针指向的内存位置不能是同一块区域,但显然对于vs2022的编译器而言是将memcpy完善了。但我们使用时还是尽量不要将两个指针指向同一个数组内的元素地址,毕竟要考虑到其它编译器并不一定完善。

画图分析2.2 my_memcpy(arr + 2, arr, sizeof(int) * 4):

在这里插入图片描述
图中每个格子代表arr数组中的一个元素,每个元素四个字节。我们利用这个简单的图分析上面模拟实现memcpy的代码,不难看出实际上拷贝是从前往后进行拷贝的,也就是从src、dest的起始位置开始往后拷贝。当拷贝完8个字节后,就变成了下面的样子:
在这里插入图片描述
这时的3和4早已被拷贝成了1和2,3和4不存在了。那么5和6就无法被拷贝成3和4了,自然而然也变成了1和2。

而解决这个问题,使用库函数memmove最好,对于这个函数,C语言的使用标准是这样的:两个指针既可以指向同一块内存区域,也可以像memcpy一样,两个指针指向不同内存区域。

2. 模拟 memmove 内存移动

如果自己实现memmove,通过上面例子出现的问题(同一块数组内存区域),如果要解决该问题,要考虑到的情况实际上也就是从前往后还是从后往前拷贝的问题,这个得由dest和src的地址大小比较后决定。

就对于上面模拟实现memcpy的问题,如果是从后往前拷贝,比如把6改成4,再把5改成3,再把3改成2,把2改成1,互不影响那么问题迎刃而解,但如果大伙认为真这么简单那就打错特错了。

对于内存而言以字节为单位,1个整型4个字节,我们实际上是要从最后一个字节开始往前一个个字节拷贝。arr数组的内存布局如下:
在这里插入图片描述
每一格都是1个字节,四格则构成一个完整的整型数据,也就是arr数组中的一个元素。格子中的值是用十六进制表示的,至于为什么是倒着存储的,这是因为当前机器以小端字节序存储数据(详细了解请看本篇文章最上面的 相关文章位置,第一个链接中的文章有解释)。

则对于dest地址值大于src的情况,可以这样拷贝:
在这里插入图片描述
而对于dest地址值小于src的情况,照常从前往后拷贝:
在这里插入图片描述

//模拟memmove(两个指针的指向可以是两块互相独立内存,也可以是同一块内存)
void* my_memmove(void* dest, const void* src, size_t bytes) {assert(dest && src);void* t = dest;// 从后面最后一个字节往前,将6改成4,再将5改成3,4改成2,3改成1,解决上面memcpy 2.2中的问题if (dest > src) {while (bytes--) { *((char*)dest + bytes) = *((char*)src + bytes);}} else if (dest < src) {     while (bytes--) {*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}} return t;
}int main() {int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 };my_memmove(arr, arr + 2, sizeof(int) * 4);for (int i = 0; i < 8; i++) {printf("%d ", arr[i]);}return 0;
}

在这里插入图片描述
成功把3 4 5 6改成1 2 3 4!


在这里插入图片描述
把1 2 3 4改成3 4 5 6也没问题!

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

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

相关文章

关于MATLAB R2022b中MATLAB function没有edit data选项的解决办法

问题描述 在MATLAB 2022b的simulink中双击MATLAB function&#xff0c;出来的是这个界面&#xff0c;而不是跳转到MATLAB的编辑窗口。因此就找不到edit data选项&#xff0c;没法完成新建data store memory 全局变量。 解决办法&#xff1a; 点击 编辑数据 按钮 在弹出的窗…

孟晚舟最新发声!华为吹响人工智能的号角,发布“全面智能化”战略部署

原创 | 文 BFT机器人 1、华为孟晚舟新发声&#xff0c;华为发布“全面智能化”战略 上周三&#xff08;9月30号&#xff09;上午&#xff0c;华为全联接大会2023正式在上海举行&#xff0c;作为华为副董事长、轮值董事长、CFO的孟晚舟代表华为再次发声&#xff01;在演讲上&am…

力扣刷题-链表-链表相交

02.07. 链表相交 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函数返…

基于springboot+vue的大学生科创项目在线管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

海大校园学习《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著

海大校园学习《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著

WARNING:tensorflow:Your input ran out of data; interrupting training. 解决方法

问题详情&#xff1a; WARNING:tensorflow:Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least steps_per_epoch * epochs batches (in this case, 13800 batches). You may need to use the repeat() funct…

【数据结构-树】哈夫曼树

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

汽车电子——产品标准规范汇总和梳理(自动驾驶)

文章目录 前言 一、分级 二、定位 三、地图 四、座舱 五、远程 六、信息数据 七、场景 八、智慧城市 九、方法论 总结 前言 见《汽车电子——产品标准规范汇总和梳理》 一、分级 《GB/T 40429-2021 汽车驾驶自动化分级》 《QC/T XXXXX—XXXX 智能网联汽车 自动驾…

C语言动态内存管理malloc、calloc、realloc、free函数的讲解

一.为什么存在动态内存管理&#xff1a; 我们知道&#xff0c;在此之前向内存申请空间的方式有以下两种&#xff1a;&#xff08;变量和数组&#xff09; 但这两种方法有几个缺陷&#xff1a; ①&#xff1a;空间开辟大小是固定的&#xff1b; ②&#xff1a;数组在声明的时候&…

Qt扫盲-QSqlQueryModel理论总结

QSqlQueryModel理论总结 一、概述二、使用1. 与 view 视图 绑定2. 分离视图&#xff0c;只存数据 一、概述 QSqlQueryModel是用于执行SQL语句和遍历结果集的高级接口。它构建在较低级的 QSqlQuery之上&#xff0c;可用于向QTableView 等视图类提供数据&#xff0c;也是使用了Q…

微信开发者工具appdata\local\微信开发者工具有啥用,能删掉吗?占用空间8G

你好这边 微信开发者工具\User Data 存储的都是一些用户开发者在工具的一些数据存储&#xff0c;不建议全部删除&#xff0c;这样可能你较常用的一些项目记录和缓存信息就会找不到&#xff0c;如果需要清理的话&#xff0c;可以考虑删除&#xff1a; WeappApplication 应用更新…

【Java 基础篇】Java 接口组成与更新详解

在Java编程中&#xff0c;接口&#xff08;interface&#xff09;是一种非常重要的概念。它允许类定义一组抽象方法&#xff0c;这些方法可以在不同的类中实现。接口在Java中起到了重要的角色&#xff0c;被广泛应用于代码的组织和设计中。本文将详细解释Java接口的组成和最新的…

QT 绘画功能的时钟

.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPaintEvent> #include <QDebug> //信息调试类 #include <QPainter> #include <QPixmap> //图像引擎类 #include <QTime> #include <QTimer> …

crypto:password

题目 下载题目所给的压缩包后解压&#xff0c;可得到文本提示信息 根据key提示&#xff0c;密码为十位 再结合生日和姓名的长度刚好十位&#xff0c;推测密码的组合为姓名字母&#xff0b;生日的组合排列 经过尝试 key为zs19900315 即得flag

详解Nacos和Eureka的区别

文章目录 Eureka是什么Nacos是什么Nacos的实现原理 Nacos和Eureka的区别CAP理论连接方式服务异常剔除操作实例方式自我保护机制 Eureka是什么 Eureka 是Spring Cloud 微服务框架默认的也是推荐的服务注册中心, 由Netflix公司与2012将其开源出来,Eureka基于REST服务开发,主要用…

crypto:摩丝

题目 根据题目所给的压缩包下载后解压&#xff0c;打开文本提示 摩斯密码&#xff0c;对照表可解码得到flag

【RabbitMQ实战】06 3分钟部署一个RabbitMQ集群

一、集群的安装部署 我们还是利用docker来安装RabbitMQ集群。3分钟安装一个集群&#xff0c;开始。 前提条件&#xff0c;docker安装了docker-compose。如果没安装的话&#xff0c;参考这里 docker-compose文件参考bitnami官网&#xff1a;https://github.com/bitnami/contai…

tsar-性能监控工具

简介 tsar是淘宝自己开发的一个采集工具&#xff0c;主要用来收集服务器的系统信息&#xff08;如cpu&#xff0c;io&#xff0c;mem&#xff0c;tcp等&#xff09;&#xff0c;以及应用数据&#xff08;如squid haproxy nginx等&#xff09;。收集到的数据存储在磁盘上&#…

机器人中的数值优化|【四】L-BFGS理论推导与延伸

机器人中的数值优化|【四】L-BFGS理论推导与延伸 往期内容回顾 机器人中的数值优化|【一】数值优化基础 机器人中的数值优化|【二】最速下降法&#xff0c;可行牛顿法的python实现&#xff0c;以Rosenbrock function为例 机器人中的数值优化|【三】无约束优化&#xff0c;拟牛…

OWASP Top 10漏洞解析(1)- A1:Broken Access Control 访问控制失效

作者&#xff1a; gentle_zhou 原文链接&#xff1a;OWASP Top 10漏洞解析&#xff08;1&#xff09;- A1:Broken Access Control 访问控制失效-云社区-华为云 Web应用程序安全一直是一个重要的话题&#xff0c;它不但关系到网络用户的隐私&#xff0c;财产&#xff0c;而且关…