memcpy 函数

news2024/11/26 15:25:07

目录

函数介绍:

函数解析:

memcpy函数复制的数据长度

内存重叠

凑不出元素的字节数 

模拟memcpy 


函数介绍:

memcpy函数是一个用于内存复制的函数,声明在 string.h 中(C++是 cstring)。

其原型是:

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

作用是:以source指向的地址为起点,将连续的n个字节数据,复制到以destin指向的地址为起点的内存中。

函数有三个参数,第一个是目标地址,第二个是源地址,第三个是数据长度。

使用memcpy函数时,需要注意:

  • 数据长度(第三个参数)的单位是字节。
  • 注意该函数有一个返回值,类型是void*,是一个指向destin的指针。
  • 这个函数在遇到 '\0' 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的。

函数解析:

  • memcpy拷贝的是空间 ,也就是字节数(1byte = 8bit)。
  • 使用的原理与strncpy类似,但还是有不同之处,列如:最后的参数不同,strncpy最后的num表示的是宽度,而memcpy表示的是字节数。
  • 以及,memcpy的前两个参数的类型是void* 表示memcpy可以调整任意类型的内存,或是说任意类型可以使用它。

memcpy函数复制的数据长度

int arr1[] = { 1, 2, 3, 4, 5, 6, 7 };
int arr2[10] = { 0 };
memcpy(arr2,arr1,28);

使用memcpy函数时,特别要注意数据长度。如果复制的数据类型是char,那么数据长度就等于元素的个数。而如果数据类型是其他(如int, double, 自定义结构体等),就要特别注意数据长度的值。

不过,无论拷贝何种数据类型,都用 n * sizeof(type_name)的写法。  

    char a[10] = "abcdefgh";
    unsigned n = 2;
    void * p = memcpy(a+3, a, n);

 以上代码将从a开始的两个字节的数据(即’a’和’b’),复制到从a+3开始的内存('d’所在的地址)。这样,'d’和’e’被替换。执行结束之后,字符数组(字符串)a的内容变为"abcabfgh"。

内存重叠

	int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	memcpy(arr1+2,arr1,20);

以上代码将1开始的20个字节复制到arr1+2开始的内存,也就是从arr[2]开始的20个字节。这样原先的内容变为了,{1,2,1,2,3,4,5,8,9,10}

但真的是这样吗?

通过上图,我们得知,因为20个字节数,我们需要复制的元素包含了1、2、3、4、5,而又因为arr1+2所在位置表示的元素是3,因在复制的过程中元素3被覆盖了,变为了元素1,元素4也是如此被覆盖成了元素2,因而当进行后续复制时,得到的结果与我们想象中的结果发生了偏移。

 

凑不出元素的字节数 

    int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    unsigned n = 5;
    void * p = memcpy(a+3, a, n);

以上代码将从a开始的5个字节的数据复制。

5个字节的数据是什么呢?前四个字节组成了一个完整的int(即第一个元素0),int类型的长度是4个字节。

第五个字节,只能取到第二个元素的第1个字节。这里又会涉及小端方式储存,那么读到的是元素1的低8位,写成十六进制即0x1。 

注:这里的存储单元是指二进制形式

由于目标地址是a+3。而因为a+3 = &a[3],所以只的是下标为3的元素,也就是元素3被替换为0。元素4写成十六进制是0x0004,低8位被替换为0x1,变为0x0001。 

所以执行结束之后,数组a的内容变为 { 0, 1, 2, 0, 1, 5, 6, 7, 8, 9 }

模拟memcpy 

void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src); 
	void* ret = dest;
	while (num--)//进行一个字节一个字节的拷贝复制
	{
		*(char*)dest = *(char*)src; 
		dest = (char*)dest + 1; 
		src = (char*)src + 1;
	}
	return ret;

}
int main()
{
	int arr1[] = { 1, 2, 3, 4, 5, 6, 7 };
	int arr2[10] = { 0 };
	my_memcpy(arr2,arr1,28);
	return 0;
}

 注:两个参数强制转化为char*类型是为了一个字节一个字节的进行拷贝复制,因为char*的数据特点和长度是1字节的原理,所以在此处更为合适使用!

 

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

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

相关文章

Excel操作技巧:如何粘贴保留单元格大小

有时我们需要在Excel中复制和粘贴并保持单元格大小。它在工作中节省了很多时间。也使数据集更具吸引力。在这篇文章中,我们将通过一些简单快捷的示例和解释来学习如何做到这一点。 一、使用上下文菜单在Excel中复制和粘贴以保持单元格大小 上下文菜单是Excel的一个重要功能。…

Openlayers 叠加天地图-中国近海海洋等深面图层服务

Openlayers 叠加天地图-中国近海海洋等深面图层服务 核心代码完整代码:在线示例 偶然发现天地图有一个近海海洋图层,觉得不错,于是尝试叠加一下,花费了一些时间,叠加成功,这里分享一下。 本文包括核心代码…

将OSGB格式数据转换为3d tiles的格式

现有需求需要将已有的一些OSGB数据加载到CesiumJS中展示,但是CesiumJS本身不支持osbg格式的数据渲染所以我们需要将其转换一下,有两种格式可以转换一种是glTF格式,另一种是我们今天要介绍的3D Tiles格式 下载开源工具 在github上其实有好多这种工具,每个工具的用法大同小异,这…

Python2021年3月Python二级 -- 编程题解析

题目一 设计一个停车场收费计算器 (收费规则,2小时以内收费5元,超出部分每小时加收2元),:要求如下: 1.设计的程序要能输入停车时间 (单位为小时,输入的小时数为整数 2.程序可以根据输入的停车时间自动计算出停车费,并且…

java操作cmd执行adb命令【搬代码】

操作具体代码如下: 须注意的是commandStr0里面如果不加 cmd /的话会报 java.io.IOException: Cannot run program "cd": CreateProcess error2, 系统找不到指定的文件。的错误 package com.znzdh.until;import java.io.BufferedReader; import java.io.…

Unity 之 方括号[ ] 的用法以及作用

文章目录 在Unity中,方括号 [ ] 通常用于表示属性、特性(Attributes)或者元数据(Metadata)。这些标记提供了附加信息,可以用于修改类、方法、字段等的行为或者在编辑器中进行设置。 以下是一些常见的用法&…

面试:25Wqps高吞吐写Mysql,100W数据4秒写完,如何实现?

25Wqps是什么概念? QPS(Queries Per Second):是衡量信息检索系统(例如搜索引擎或数据库)在一秒钟内接收到的搜索流量的一种常见度量。 通过概念我们能很清楚知道 QPS 并发数/响应时间,即100W…

conda创建python虚拟环境

1.查看当前存在那些虚拟环境 conda env list conda info -e 2.conda安装虚拟环境 conda create -n my_env_name python3.6 2.1在anaconda下改变python版本 当前3.7 安装3.7 conda create -n py37 python3.7 conda activate py37 conda create -n py37 python3.7conda a…

多通道振弦数据记录仪应用于大坝岩土工程监测

多通道振弦数据记录仪应用于大坝岩土工程监测 随着现代科技的不断发展,多通道振弦数据记录仪的应用越来越广泛,其中在大坝岩土工程监测中的应用也越来越普遍。多通道振弦数据记录仪通过采集振动信号的信息,可以有效地监测大坝的安全性和稳定…

【校招VIP】数据库理论之存储过程

考点介绍: 存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能…

给数组中多次出现的数据添加不同的标记

/*** params 取数组中第二次出现的元素之后的数据* returns*/ export const getElementsAfterSecondOccurrence (arr, column, targetValue) > {let count 0;let secondIndex -1;for (let i 0; i < arr.length; i) {if (arr[i][column] targetValue) {count;if (co…

VmWare安装CentOs8

文章目录 创建虚拟机1、创建虚拟机2、选择虚拟机硬件兼容性3、安装客户机操作系统4、安装客户机操作系统5、命名虚拟机6、处理器配置7、分配虚拟机的内存8、配置网络类型9、选择I/O控制器类型10、选择磁盘类型11、选择磁盘12、指定磁盘容量13、指定磁盘文件14、完成创建 2.安装…

STM32的HAL库的定时器使用

用HAL库老是忘记了定时器中断怎么配置&#xff0c;该调用哪个回调函数。今天记录一下&#xff0c;下次再忘了就来翻一下。 系统的时钟配置&#xff0c;定时器的时钟是84MHz 这里定时器时钟是84M&#xff0c;分频是8400后&#xff0c;时基就是1/10000s&#xff0c;即0.1ms。Per…

百度文心一言GPT免费入口也来了!!!

文心一言入口地址&#xff1a;https://cloud.baidu.com/wenxin.html?daohang

【校招VIP】前端校招考点之UDP

考点介绍&#xff1a; UDP是非面向连接协议&#xff0c;使用udp协议通讯并不需要建立连接&#xff0c;它只负责把数据尽可能发送出去&#xff0c;并不可靠&#xff0c;在接收端&#xff0c;UDP把每个消息断放入队列中&#xff0c;接收端程序从队列中读取数据。 『前端校招考点…

华为云 sfs 服务浅谈

以root用户登录弹性云服务器。 以root用户登录弹性云服务器。 安装NFS客户端。 查看系统是否安装NFS软件包。 CentOS、Red Hat、Oracle Enterprise Linux、SUSE、Euler OS、Fedora或OpenSUSE系统下&#xff0c;执行如下命令&#xff1a; rpm -qa|grep nfs Debian或Ubuntu系统下…

微信小程序 校园周边美食商城分享系统

管理员、会员、商家可通过Android系统手机打开系统&#xff0c;注册登录后可进行管理员后端&#xff1b;首页、个人中心、会员管理、商家管理、美食类型管理、美食信息管理、美食交流、我的收藏管理、系统管理、订单管理&#xff0c;会员前端&#xff1b;首页、美食信息、美食交…

PHP8的箭头函数-PHP8知识详解

php 7.4 引入了箭头函数&#xff08;Arrow Functions&#xff09;&#xff0c;并在 PHP 8 中得到了进一步改进和扩展。 箭头函数是一种更简洁的匿名函数形式&#xff0c;它们提供了一种更便捷的方式来定义轻量级的、单行的回调函数。 箭头函数的语法如下&#xff1a; fn (参…

我的创作纪念日----探索创作之旅

创作之旅 创作之始启程追寻&#xff1a;寻觅灵感的起点思绪迸发&#xff1a;创意萌芽与滋长 创作之途探索未知&#xff1a;友人的帮助与指导 创作之行倾听内心&#xff1a;创意荒漠的探寻 主页传送门&#xff1a;&#x1f4c0; 传送 创作之始 ​ ​  在我尚未察觉的瞬间&…