当前位置: 首页 > news >正文

【C语言 模拟实现memcpy函数、memcpy函数】

C语言程序设计笔记---027

  • C语言之模拟实现memcpy函数、memcpy函数
    • 1、介绍memcpy函数
      • 1.1、模拟实现memcpy函数
    • 2、介绍memmove函数
      • 2.1、模拟实现memmove函数
    • 3、结语

C语言之模拟实现memcpy函数、memcpy函数

前言:
通过C语言内存函数的知识,这篇将对memcpy函数、memcpy函数进行深入学习底层原理的知识,并模拟实现对应功能。

/知识点汇总/
内存相关的函数
1.memcpy –strcpy
2.memmove
3.memset
4.memcmp — strcmp

1、介绍memcpy函数

函数原型:void *memcpy( void dest, const void src, size_t count ); ---- void 说明,兼容任意类型
函数功能:将源头内存的数据,拷贝到目标内存中,返回值类型为void

头文件:<string.h>
使用注意事项
(1)、与strncpy不同的是,参数num和count。一个是指需要拷贝的元素个数,一个是指需要拷贝的元素字节大小
(2)、相比strcpy函数仅仅是操作字符串进行拷贝,而memcpy内存中的数据,不仅仅是操作字符。
示例代码如下

#include <stdio.h>
#include <string.h>
int main()
{int arr1[10] = { 0 };int arr2[] = { 1,2,3,4,5 };memcpy(arr1, arr2, 20);//20 == 4*5int sz = sizeof(arr1) / sizeof(arr1[0]);for (int i = 0; i < sz; i++){printf("%d ", arr1[i]);}return 0;
}

1.1、模拟实现memcpy函数

#include <stdio.h>
#include <string.h>
#include <assert.h>
//注意:void* 不能进行运算操作
//另外,这里必须使用(char*)进行操作,因为如果是其它类型就会造成数据上的丢失等问题 --- 联想类似于qsort一个个字节进行操作
void* my_memcpy(void* dest, const void* src, size_t sz)//sz拷贝多少个字节
{assert(dest && src);while (sz--)//以一个字节一个字节的拷贝{*(char*)dest = *(char*)src;dest = (char*)dest + 1;//注意:强制类型转换具备临时属性,所以需要(char*)dest+1来赋值保存数据,不能用dest++src =  (char*)src + 1;}
}
int main()
{int arr1[10] = { 0 };int arr2[] = { 1,2,3,4,5 };my_memcpy(arr1, arr2, 20);//20 == 4*5for (int i = 0; i < 5; i++){printf("%d ", arr1[i]);}return 0;
}

解释说明
1.assert是断言,参数为指针,防止传参过来是空指针避免野指针的问题
2.用一个指针变量始终保存目标字符串的起始地址,以免目标起始地址发生改变,导致函数的返回值错误
3.sz–因为memcpy是以字节为单位进行的拷贝,所以为了兼容多种类型,就需要强转为char*类型之后再操作。(可回顾前面篇章,模拟qsort函数的内容)

扩展:memcpy对同一内存空间的操作问题
以我们自己模拟的memcpy函数,导致问题的原因:
调试可知,它是以一个一个字节进行的拷贝,
所以比如:对0x11223344进行拷贝为01操作是0x01010101达不到我们的预期,
而我们预期应该是0x11223301,然后下一个元素比如0x11224401
但是,库函数的memcpy在当前的编译器条件下,弥补了这样的错误问题。说明库函数作者完善的很全面,同时更复杂。

2、介绍memmove函数

函数原型:void *memmove( void dest, const void src, size_t count );
函数功能:将源头内存的数据。拷贝到目标内存中,且与memcpy相比可以拷贝同一空间的数据,返回值类型为void

头文件:<string.h>
使用注意事项
(1)、memcpy只能对不同空间内存之间的数据进行操作
即:不重叠内存的拷贝,可以使用memcpy,而重叠的内存空间则需要用memmove函数
示例代码如下

#include <stdio.h>
#include <string.h>
int main()
{int arr1[10] = { 0 };int arr2[] = { 1,2,3,4,5 };memmove(arr1, arr2, 20);//20 == 4*5int sz = sizeof(arr1) / sizeof(arr1[0]);for (int i = 0; i < sz; i++){printf("%d ", arr1[i]);}return 0;
}

2.1、模拟实现memmove函数

#include <stdio.h>
#include <assert.h>
void* my_memmove(void* dest, const void* src, size_t sz)
{assert(dest && src);char* ret = (char*)dest;if (dest < src)//从前向后拷贝{while (sz--){*((char*)dest) = *((char*)src);dest = (char*)dest + 1;src = (char*)src + 1;}}else//从后向前拷贝{while (sz--)//sz-- 先用再减,即先判断sz=20为真,用完后减1进入循环,此时sz=19{*((char*)dest + sz) = *((char*)src + sz);}}return ret;
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr + 2, arr, 20);//20 == 4*5int sz = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

解释说明
1.assert是断言,参数为指针,防止传参过来是空指针避免野指针的问题
2.用一个指针变量始终保存目标字符串的起始地址,以免目标起始地址发生改变,导致函数的返回值错误
3.dest < src表示目标空间地址在源地址前面,适合从源地址的高位开始拷贝,即从前向后拷贝
值得注意的是,因为memmove是以字节为单位进行的拷贝,所以为了兼容多种类型,就需要强转为char*类型之后再操作。(可回顾前面篇章,模拟qsort函数的内容)
4.相反否则就是,目标空间地址在源地址后面,适合从源地址的低位开始拷贝,即从后向前拷贝
值得注意的是,对于源地址的最后一个数据地址是指针+sz从后向前偏移。

小结
1.memcpy只能对不同空间内存之间的数据进行操作
即:不重叠内存的拷贝,可以使用memcpy,而重叠的内存空间则需要用memmove函数
2.库函数可以实现,标准规定:
以memcpy来实现不重叠的内存的拷贝,且要求能达到60即可
以memmove来实现重叠内存的拷贝
3.但是,发现当前的编译环境下,memcpy同样能实现重叠内存的拷贝,远远满足60分的要求,100分,所以于编译环境相关,建议相应的功能交给适合的函数实现即可

3、结语

学习函数的最实用的方式就是用自己的逻辑简单实现一些类似的功能
半亩方糖一鉴开,天光云影共徘徊。
问渠哪得清如许?为有源头活水来。–朱熹(观书有感)

相关文章:

【C语言 模拟实现memcpy函数、memcpy函数】

C语言程序设计笔记---027 C语言之模拟实现memcpy函数、memcpy函数1、介绍memcpy函数1.1、模拟实现memcpy函数 2、介绍memmove函数2.1、模拟实现memmove函数 3、结语 C语言之模拟实现memcpy函数、memcpy函数 前言&#xff1a; 通过C语言内存函数的知识&#xff0c;这篇将对memc…...

opencv视频文件的读取,处理与保存

文章目录 opencv视频文件的读取&#xff0c;处理与保存一、视频文件的读取&#xff1a;1、cv::VideoCapture是OpenCV库中用于处理视频输入的类&#xff0c;它提供了一种简单的方法来从摄像头&#xff0c;视频文件、或图像序列中读取帧&#xff1b;&#xff08;1&#xff09;打开…...

java - 七大比较排序 - 详解

前言 本篇介绍了七大比较排序&#xff0c;直接插入排序&#xff0c;希尔排序&#xff0c;冒泡排序&#xff0c;堆排序&#xff0c;选择排序&#xff0c;快速排序&#xff0c;归并排序&#xff0c;一些简单思想代码实现&#xff0c;如有错误&#xff0c;请在评论区指正&#xf…...

项目集成七牛云存储sdk

以PHP为例 第一步&#xff1a;下载sdk PHP SDK_SDK 下载_对象存储 - 七牛开发者中心 sdk下载成功之后&#xff0c;将sdk放入项目中&#xff0c;目录选择以自己项目实际情况而定。 注意&#xff1a;在examples目录中有各种上传文件的参考示例&#xff0c;这里我们主要参考的是…...

docker-compose一键启动neo4j

下载镜像 docker pull neo4j:3.5.22-community 编写配置文件 参考文档 编写docker-compose.yml文件 version: "3"services:neo4j:image: neo4j:3.5.22-communitycontainer_name: neo4j restart: alwaysports:- 7474:7474- 7687:7687environment:- NEO4J_AUTH:ne…...

深入剖析@ConfigurationProperties注解

当我们构建Spring Boot应用程序时&#xff0c;配置属性通常是不可或缺的一部分。Spring Boot提供了多种方式来管理这些属性&#xff0c;其中之一是使用ConfigurationProperties注解。这篇博客将详细解释ConfigurationProperties注解以及如何使用它来管理和映射配置属性。 什么…...

北京开发APP需要多少钱

北京开发一个移动应用&#xff08;APP&#xff09;的费用因多种因素而异&#xff0c;包括项目的规模、复杂性、所需功能、设计要求、技术选择、开发团队的经验和地理位置等。一般来说&#xff0c;北京的APP开发费用通常较高&#xff0c;因为这是中国的主要技术和创新中心之一&a…...

self-attention、transformer、bert理解

参考李宏毅老师的视频 https://www.bilibili.com/video/BV1LP411b7zS?p2&spm_id_frompageDriver&vd_sourcec67a2725ac3ca01c38eb3916d221e708 一个输入&#xff0c;一个输出&#xff0c;未考虑输入之间的关系&#xff01;&#xff01;&#xff01; self-attention…...

junit @ExcludePackages排除多个包

在JUnit中&#xff0c;可以使用ExcludePackages注解来排除多个包。该注解可以用在测试类或测试方法上。 如果要排除多个包&#xff0c;可以在ExcludePackages注解的value属性中使用数组来指定要排除的包名。例如&#xff0c;要排除包com.example.package1和com.example.packag…...

Explain执行计划字段解释说明---select_type、table、patitions字段说明

1、select_type的类型有哪些 2、select_type的查询类型说明 1、SIMPLE 简单的 select 查询,查询中不包含子查询或者UNION 2、PRIMARY 查询中若包含任何复杂的子部分&#xff0c;最外层查询则被标记为Primary 3、DERIVED 在FROM列表中包含的子查询被标记为DERIVED(衍生)&…...

云原生微服务 第六章 Spring Cloud Netflix Eureka集成远程调用、负载均衡组件OpenFeign

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 文章目录 系列文章目录前言1、OpenFeign的实现…...

四、2023.9.30.C++面向对象end.4

文章目录 49、 简述一下什么是常函数&#xff0c;有什么作用&#xff1f;50、 说说什么是虚继承&#xff0c;解决什么问题&#xff0c;如何实现&#xff1f;51、简述一下虚函数和纯虚函数&#xff0c;以及实现原理&#xff1f;52、说说纯虚函数能实例化吗&#xff0c;为什么&am…...

【Java】包

package 包&#xff08;package&#xff09;:其实就是文件夹。 作用&#xff1a;对类进行分类管理。 包的定义格式 格式&#xff1a;package 包名&#xff08;多级包用 . 分开&#xff09; 范例&#xff1a;package com.mayikt.demo01 带包的Java类编译和执行 1. 手动建包 安装…...

Hive【Hive(二)DML】

启动 hive 命令行&#xff1a; hive DML 数据操作 1、数据导入 1.1、向表中装载数据&#xff08;load&#xff09; 语法&#xff1a; hive> load data [local] inpath 数据的path [overwrite] into table student [partition (partcol1val1,…)];&#xff08;1&#x…...

HTTP的请求方法,空行,body,介绍请求报头的内部以及粘包问题

目录 一、GET与POST简介 二、空行和body 三、初识请求报头以及粘包问题 四、认识请求报头剩余部分 一、GET与POST简介 GET https://www.sogou.com/HTTP/1.1 请求报文中的方法&#xff0c;是最常规的方法&#xff08;获取资源&#xff09; POST&#xff1a;传输实体主体的方法…...

win10 ip设置

百度安全验证...

alibaba dragonwell jdk

阿里巴巴Dragonwell8快速指南 dragonwell-project/dragonwell8 Wiki GitHub 阿里巴巴Dragonwell8用户指南 dragonwell-project/dragonwell8 Wiki GitHub 阿里巴巴Dragonwell8常见问题 dragonwell-project/dragonwell8 Wiki GitHub...

jvm内存分配与回收策略

自动内存管理 解决两个问题 自动给对象分配内存 对象一般堆上分配&#xff08;而实际上也有可能经过即时编译后被拆散为标量类型并间接地在栈上分配&#xff09; 新生对象通常会分配在新生代&#xff0c;少数情况下&#xff08;例如对象大小超过一定阈值&#xff09;也可能…...

【Vue2和Vue3的双向绑定区别】

Vue2和Vue3的双向绑定区别 vue2 双向绑定原理vue3 双向绑定原理Vue2和Vue3的双向绑定存在以下区别&#xff1a; vue2 双向绑定原理 Vue2 双向绑定的实现主要依赖于 Object.defineProperty() 方法和观察者模式&#xff0c;其中 Object.defineProperty() 方法用于定义属性的 get…...

【再识C进阶3(下)】详细地认识字符分类函数,字符转换函数和内存函数

前言 &#x1f493;作者简介&#xff1a; 加油&#xff0c;旭杏&#xff0c;目前大二&#xff0c;正在学习C&#xff0c;数据结构等&#x1f440; &#x1f493;作者主页&#xff1a;加油&#xff0c;旭杏的主页&#x1f440; ⏩本文收录在&#xff1a;再识C进阶的专栏&#x1…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...