使用memcpy函数时要注意拷贝数据的长度
memcpy函数简介
memcpy函数是C/C++语言中的一个用于内存复制的函数,声明在 string.h 中(C++是 cstring)。其原型是:
void *memcpy(void *destin, void *source, unsigned n);
作用是:以source指向的地址为起点,将连续的n个字节数据,复制到以destin指向的地址为起点的内存中。
函数有三个参数,第一个是目标地址,第二个是源地址,第三个是数据长度。
使用memcpy函数时,需要注意:
- 数据长度(第三个参数)的单位是字节(1byte = 8bit)。
- 注意该函数有一个返回值,类型是
void*,是一个指向destin的指针。
memcpy函数复制的数据长度
使用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",返回值p即为a的地址(p == a)。
再以int类型为例说明:
int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
unsigned n = 5;
void * p = memcpy(a+3, a, n);
int类型的长度是4个字节。以上代码将从a开始的5个字节的数据复制。5个字节的数据是什么呢?前四个字节组成了一个完整的int(即第一个元素0)。第五个字节,只能取到第二个元素的第1个字节。这里又会涉及到big-endian和little-endian的问题。假设是小端方式储存(更常见),那么读到的是元素1的低8位,写成十六进制即0x1。
目标地址是a+3。由于指针加减常数,单位是与类型保持一致的,也就是在a的基础上,增加3倍int长度,对应的是元素3的地址。元素3被替换为0。元素4写成十六进制是0x0004,低8位被替换为0x1,变为0x0001。
所以执行结束之后,数组a的内容变为 { 0, 1, 2, 0, 1, 5, 6, 7, 8, 9 },返回值p即为a的地址(p == a)。
根据上面的解释,如果把程序里的n改为6、7、8,那么结果都是一样的。因为数字1和4的二进制表示除了低8位不同,高位都是0。
倘若高位不相同,那么结果就没那么简单了。还是以int数组为例:
int a[10] = { 0, -1, 2, 3, 4, 5, 6, 7, 8, 9 };
unsigned n = 5;
memcpy(a+3, a, n);
复制5个字节的数据,前4个字节组成了一个int,即第一个元素0。那么元素3被替换为0。第5个字节从-1中取。-1的十六进制表示为0xFFFF,第5个字节的数据是0xF。元素4变为0x000F,即15。数组a变为 { 0, -1, 2, 0, 15, 5, 6, 7, 8, 9 }。
如果 n = 6,那么4变为```0x00FF``,即255。数组a变为 { 0, -1, 2, 0, 255, 5, 6, 7, 8, 9 }。
可以看出,如果你想用memcpy复制元素,那么一定要写对数据长度。如果要完整地复制 n 个 int 类型元素,那么写法如下:
int a[10] = { 0, -1, 2, 3, 4, 5, 6, 7, 8, 9 };
unsigned n = 5 * sizeof(int);
memcpy(a+3, a, n);
数组a变为 { 0, -1, 2, 0, -1, 2, 0, -1, 8, 9 }。
如果是其他类型,用法也是一样的。
好的习惯是,如果拷贝何种数据类型,都用 n * sizeof(type_name)的写法。
使用memcpy函数时要注意拷贝数据的长度的更多相关文章
- sprintf、strcpy 及 memcpy 函数区别
这些函数的区别在于 实现功能 以及 操作对象 不同.strcpy 函数操作的对象是 字符串 ,完成 从 源字符串 到 目的字符串 的 拷贝 功能. sprintf 函数操作的对象 不限于字符串 :虽然 ...
- memmove和memcpy函数的区别及实现
一.memmove()和memcpy()函数和strcpy()函数的区别: (1)使用的类型不同,strcpy()函数只对字符串进行操作:memmove()和memcpy()函数对所有类型都适用,为内 ...
- 一个按比特位拷贝数据的函数copybits
一个按比特位拷贝数据的函数 没有进行特别的优化.其实还可以在拷贝源开始位置和目标开始位置是2的整数倍位置的时候进行优化. 说明 这个函数用于从src数组首地址跳过sbb个字节,又跳过ssb个比特位,拷 ...
- ajax请求为异步操作时,返回的数据不会被并列函数执行
ajax请求为异步操作时,返回的数据不会被并列函数执行
- C语言之memcpy函数
昨天自己动手实现memcpy这个函数,用一个例程试了一下,结果正确,满心欢心,可是有些地方想不明白,于是百度了一下,结果自己写的函数简直无法直视. 觉得还是写个总结,以示教训. 先贴上我自己的函数: ...
- memcpy函数的使用方法
c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中. 1.函数原型 void *memcpy(void * ...
- memset和memcpy函数、atoi函数
memset void *memset(void *s,int c,size_t n) 总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c.如下: // 1.将已开辟内存空间s的首n个字节 ...
- 实现memcpy()函数及过程总结
1.为什么会写memcpy 在之前的应聘笔试上遇到一道笔试题,题目要求实现一个my_memcpy函数.函数原型:void * my_memcpy(void *dst, const void *src, ...
- C/C++ memcpy函数的用法
功能 memcpy指的是c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中 头文件 所在头文件 <s ...
随机推荐
- Sql操作时间
--. 当前系统日期.时间 -- ::27.277 --.时间操作 dateadd 在向指定日期加上一段时间的基础上,返回新的 datetime 值 dateadd(datepart,number,d ...
- scala 中的匹配模式
unapply 仅作匹配,不作其它输出.返回 Boolean 值 object UpperCase { def unapply(s: String): Boolean = s.toUpperCase ...
- 使用SpringBoot访问jsp页面
1 编写application.yml文件 spring: mvc: view: suffix: .jsp prefix: /jsp/ 2 创建Controller层 @Controller @Req ...
- UFUN函数 UF_CFI函数(uc4504,uc4540,uc4514,uc4547,UF_CFI_ask_file_exist )
UF_initialize(); //指定本地数据文件的路径 char file_spec[]="D://Program Files//Siemens//NX 8.0//UGII//zyTO ...
- Lightning Web Components html_templates(三)
Lightning Web Components 强大之处在于模版系统,使用了虚拟dom 进行智能高效的组件渲染. 使用简单语法以声明方式将组件的模板绑定到组件的JavaScript类中的数据 数据绑 ...
- element ui 里面的table怎么弹出一个框让表中数据点击出现弹框
<el-table-column label="团队" prop="name" min-width="120px" align=&qu ...
- Windows 安装R
下载 R 的安装包 双击 安装包 进行安装 安装完成 测试 修改 R 中的CRAN镜像 添加到 Windows 的环境变量中 测试
- 新版本Mariadb安装后相关问题的解决
给新机器Ubuntu安装的Mariadb后无法登录,通过网上各种方法修改root用户密码,仍然无法解决,耗费几个小时! 经过看日志和查手册,发现原因如下: ubuntu确实安装没有启用root用户,所 ...
- Linux 文件系统磁盘空间与连接文件
磁盘与目录的容量 我们知道磁盘的整体数据hi在superblock块中,但是各文件的容量则在inode中记载. df:列出文件系统的整体磁盘使用量 由于df主要读取的数据几乎都是针对整个文件系统,因此 ...
- flask + Python3 实现的的API自动化测试平台---- IAPTest接口测试平台,更名:FXTest 接受定制开发(java版开发完毕)
**背景: 1.平时测试接口,总是现写代码,对测试用例的管理,以及测试报告的管理持久化做的不够, 2.工作中移动端开发和后端开发总是不能并行进行,需要一个mock的依赖来让他 ...