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

memcpy内存拷贝函数

目录

一、memcpy内存拷贝函数

注意事项

二、memcpy与strcpy对比

三、模拟实现memcpy函数

四、memcpy函数不能进行两块存在内存重叠的空间的内存拷贝

五、改进my_memcpy函数


一、memcpy内存拷贝函数

头文件:string.h

函数原型:void* memcpy(void* destination , const void* source , size_t num)

函数作用:将源地址中num个字节的内容拷贝到目标地址中

参数分析:

void *是不指定具体类型指针,意味着该函数可以拷贝任意类型的数据

destination是目标地址,即将源地址的内容拷贝到目标地址中

source是源地址,为目标地址提供拷贝内容

num是拷贝多少个字节

实例代码1:两个数组空间的拷贝

char arr1[] = { 5,4,3,2,1 };
char arr2[] = { 1,2,3,4,5,6,7,8,9,10 };
memcpy(arr2, arr1, sizeof(arr1[0]) * 5);for (int i = 0; i < 10; i++)
{printf("%d ", arr2[i]);
} 

实例代码2:destination和source不一定是数组,任意可读写的地址空间即可

char arr[20] = "abcdefg";
char* p = "123456789";
memcpy(arr + 2, p + 5, sizeof(char) * 4);printf("%s\n", arr);

注意事项:

1.拷贝时destination地址的空间需要足够大,至少大于等于num个字节

2.如果destination地址空间存在数据,将会被新数据覆盖

3.memcpy不能进行有内存重叠的两个地址的内存拷贝

二、memcpy与strcpy对比

memcpy是内存拷贝函数,strcpy是字符串拷贝函数

strcpy函数原型:char *strcpy(char *str1, const char *str2)

strcpy函数作用:将字符串str2中的内容拷贝到字符串str1中

对比memcpy函数:

1.memcpy函数逐字节拷贝,strcpy函数遍历str2时遇到\0即停止拷贝,并将\0也拷贝到str1中

2.memcpy函数可以拷贝任意类型数据,strcpy函数只能拷贝字符串

三、模拟实现memcpy函数

注意:优先级:后置++  >  强制类型转换,所以destination和source的强制类型转换需要加括号

void* my_memcpy(void* destination, const void* source, size_t num)
{if (destination == NULL || source == NULL){return NULL;}for (int i = 0; i < num; i++){*(char*)destination = *(char*)source;((char*)destination)++;((char*)source)++;}
}

实例代码:

char arr[] = "123456789";
memcpy(arr, arr + 5, 3);
printf("%s\n", arr);//678456789

四、memcpy函数不能进行两块存在内存重叠的空间的内存拷贝

VS改进后的memcpy函数可以进行内存重叠空间的拷贝:

C语言标准规定,memcpy函数不能进行两块有内存重叠的的空间的内存拷贝,但是在VS编译器下实际测试时,这是由于VS对memcpy函数进行了改进,使得其可以进行内存重叠的空间的拷贝。

char arr[] = "123456789";
memcpy(arr + 2, arr, 5);//121234589
printf("%s\n", arr);

模拟实现的my_memcpy函数不能进行内存重叠空间的拷贝:

但是当使用模拟实现的my_memcpy函数进行拷贝时,结果不尽人意……

结果并非预期的121234589,而是121212189

	char arr[] = "123456789";my_memcpy(arr + 2, arr, 5);//121234589printf("%s\n", arr);

原因分析:

这是因为在进行内存重叠的两块空间拷贝时,会发生未拷贝的被已拷贝的数据覆盖

例如:将源空间的12345,拷贝到目标空间的34567

当1、2拷贝到3、4的位置时,数组变为121256789,源空间需要拷贝的3、4被1、2覆盖,无法进行拷贝,只能再将1、2拷贝到目标空间,显然这是错误的

五、改进my_memcpy函数

解决上述问题,需要改进的my_memcpy函数的算法

将拷贝的类型分为两类:1.源空间在目标空间前  2.目标空间在源空间前

1.源空间在目标空间前

如下图,常规方法从前向后拷贝(1~3,2~4,……),需要改进为从后向前拷贝(5~7,4~6,……),这样被覆盖的数据已经拷贝完了 ,不影响后续的拷贝

2.目标空间在源空间前

如下图,需要从前向后拷贝(3~1,4~2,……)

总体原则:第一次拷贝的空间不能覆盖源空间

改进后的my_memcpy函数:

void* my_memcpy(void* destination, const void* source, size_t num)
{if (destination == NULL || source == NULL){return NULL;}if (source < destination)//从后向前拷贝{for (int i = num - 1; i >= 0; i--){*((char*)destination + i) = *((char*)source + i);}}else//从前向后拷贝{for (int i = 0; i < num; i++){*(char*)destination = *(char*)source;((char*)destination)++;((char*)source)++;}}
}

测试代码:

char arr[] = "123456789";
my_memcpy(arr + 2, arr, 5);//121234589
printf("%s\n", arr);

相关文章:

memcpy内存拷贝函数

目录 一、memcpy内存拷贝函数 注意事项 二、memcpy与strcpy对比 三、模拟实现memcpy函数 四、memcpy函数不能进行两块存在内存重叠的空间的内存拷贝 五、改进my_memcpy函数 一、memcpy内存拷贝函数 头文件&#xff1a;string.h 函数原型&#xff1a;void* memcpy(void* …...

数组模拟堆

文章目录 QuestionIdeasCode Question 维护一个集合&#xff0c;初始时集合为空&#xff0c;支持如下几种操作&#xff1a; I x&#xff0c;插入一个数 x &#xff1b; PM&#xff0c;输出当前集合中的最小值&#xff1b; DM&#xff0c;删除当前集合中的最小值&#xff08;数…...

【深度学习基础知识(一):卷积神经网络CNN基础知识】

深度学习基础知识 深度学习基础知识&#xff08;一&#xff09;&#xff1a;卷积神经网络CNN基础知识 卷积神经网络CNN基础知识 0、目录 1. CNN卷积神经网络的特点 2. 卷积操作基础知识 2.1 卷积操作的概念2.2 卷积操作的种类2.3 卷积操作后特征图谱大小计算公式 3. 池化操…...

Git使用入门

一、Git简介 Git 是一个开源的分布式版本控制系统。 Git版本控制的功能为保存不同版本的代码&#xff0c;保存代码的地方叫做仓库。 每个仓库中有多个分支&#xff0c;每个分支上又有很多节点&#xff0c;每个节点代表一个版本&#xff0c;不同的分支可以进行合并&#xff0…...

电机矢量控制算法和例程

电机矢量控制算法是一种高级的电机控制方法&#xff0c;它通过将电机转子空间矢量转换到旋转坐标系中&#xff0c;并在该坐标系中进行控制来实现对电机的精确控制。下面是对电机矢量控制算法的详细解释&#xff1a; 坐标系变换&#xff1a;电机矢量控制首先将电机转子空间矢量变…...

std::string_view概念原理及应用

概念 使用const string&作为参数是先使用字符串字面量编译器会创建一个临时字符串对象然后创建std::string。 或者一个函数提供char*和const string&参数的两个版本函数&#xff0c;不是优雅的解决方案。 于是需要一个只使用内存不维护内存的类。 原理 在visual s…...

lodash库_.chunk、_.pick、_.omit、_.cloneDeep、_.debounce方法

lodash 模块化、高性能的 JavaScript 实用工具库。官方文档&#xff1a;https://www.lodashjs.com 1.对数组进行分组 _.chunk(array, [size1]) 使用场景&#xff0c;如移动端页面一行能放5个元素&#xff0c;总共7条数据&#xff0c;将一维数组转为二维数组&#xff0c;让一个…...

Java使用FFmpeg对视频文件打标记

免安装 FFmpeg <dependency><groupId>ws.schild</groupId><artifactId>jave-all-deps</artifactId><version>3.0.1</version><exclusions><!-- 排除windows 32位系统 --><exclusion><groupId>ws.sch…...

Redux 学习笔记

在使用 React Redux 前&#xff0c;我们首先了解一下 Redux 的一些基础知识。 Redux 是 JavaScript 应用程序中用于状态管理的容器。它不依赖于任何框架&#xff0c;可以与任何 UI 库和框架一起使用。在应用程序中使用 Redux 时&#xff0c;Redux 是以可预测的方式管理状态。 …...

【Bug】8086汇编学习

文章目录 随笔Bug1、masm编译报错&#xff1a;Illegal use of register2、debug中使用段前缀3、[idata]在编译器中的处理4、push立即数报错5、报错&#xff1a;improper operand type6、程序莫名跳转到未知位置 (doing)7、DOSBox失去响应8、程序运行显示乱码9、程序运行导致DOS…...

JetBrains系列IDE全家桶激活

jetbrains全家桶 正版授权&#xff0c;这里有账号授权的渠道&#xff1a; https://www.mano100.cn/thread-1942-1-1.html 附加授权后的一张图片...

洛谷p1618三连击

import java.util.Scanner; //将 1-9 共9个数分成3组&#xff0c;分别组成3个三位数&#xff0c;且使这3个三位数构成A:B:C的比例&#xff0c;试求出所有满足条件的3个三位数。不满足输出“No!!!”。 public class Main {public static void main(String[] args) {Scanner sc …...

微信公众号h5写一个全局调用微信分享功能

1. 首先先安装依赖 npm install weixin-js-sdk --save 2. app.vue文件 <script> export default { onLaunch: function(e) {}, onShow: function(e) { console.log(App Show页面初始); // 路由参数存缓存的 这是为了防止他…...

聊聊精益需求的产生过程

这是鼎叔的第七十八篇原创文章。行业大牛和刚毕业的小白&#xff0c;都可以进来聊聊。 欢迎关注本公众号《敏捷测试转型》&#xff0c;星标收藏&#xff0c;大量原创思考文章陆续推出。本人新书《无测试组织-测试团队的敏捷转型》​​​​​​​​​​​​​​已出版&#xff…...

Linux - 还不懂 gdb 调试器?(调试软件)

前言 当前&#xff0c;我们可以使用 make/makefile 来程序化执行代码文件&#xff1b;可以使用 gcc/g 等编译器来编译代码&#xff1b;可以使用 vim 编辑器来编写代码&#xff1b;其实在 Linux 当中还有一个工具&#xff0c;可以实现调试工作&#xff0c;这个工具就是 -- gdb。…...

Linux:程序地址空间/虚拟地址等相关概念理解

文章目录 程序地址空间虚拟地址和物理地址地址的转换地址空间是什么&#xff1f; 程序地址空间 在C和C程序中&#xff0c;一直有一个观点是&#xff0c;程序中的各个变量等都会有一定的地址空间&#xff0c;因此才会有诸如取地址&#xff0c;通过地址访问等操作&#xff0c;那…...

Python之爬虫

目录 HTTP请求HTTP响应获得页面响应伪装用户访问打包数据爬取豆瓣top250 HTTP请求 HTTP&#xff1a;HypertextTransferProtcol 超文本传输协议 1、请求行 POST/user/info?new_usertrue HTTP/1.1#资源了路径user/info 查询参数new_usertrue 协议版本HTTP/1.1 2、请求头 Ho…...

打造自己的前端组件库(奶妈版,超详细)

打造自己的前端组件库 demo是开源的&#xff0c;自己上npm 或者 github 上都能搜到 新建vue项目(sass js vue2) vue create yt-ui 修改文件目录(如下) 修改&#xff1a; 1.src 更名 examples; 2. src/components移动到项目最外层&#xff1b;3.vue.config.js更改入口文件 /…...

6.调制阶数相关

1、调制阶数与峰均比的关系 调制阶数&#xff08;modulation order&#xff09;对峰均比&#xff08;有一定的影响。 峰均比是用于衡量调制信号或波形在幅度上的动态范围的指标。它表示信号的最大峰值与平均功率之间的比值。较高的峰均比可能导致信号在传输或放大过程中出现过…...

Maven多模块管理(转载)

注意&#xff1a;父模块需设定打包方式为pom https://cloud.tencent.com/developer/article/1667275 dependencyManagement 统一管理子类依赖版本 在父类maven中加入&#xff0c;不会继承给子类&#xff0c;只能规定子类的依赖版本&#xff0c;子类加入dependence后无需写入 …...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...