当前位置: 首页 > 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后无需写入 …...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...