浅谈memcpy和memmove

POSIX和C标准明确表示,使用重叠区域的mem‐cpy()会产生未定义的行为。
memcpy和memmove的区别是:当内存发生局部重叠时memmove函数能够保证拷贝结果的正确性,而memcpy则不能保证拷贝结果的正确性;当内存没有发生重叠的时候两个函数的结果是一样的。

为什么说memcpy不能保证拷贝结果的正确性,可以看看下面这个例子。

当src和dst重合(即内存重叠)且src小于dst且dst < src+count时,如下图所示:

如果从低地址开始拷贝,那么源数据在使用前会被覆盖。除了这种情况,其他情况下都可以保证memcpy拷贝正确。

为什么memmove可以保证拷贝的结果是正确的?
因为memmove是在memcpy的基础上对所有可能的情况都做了处理;简单的说就是在内存重叠且源数据会被覆盖的情况下选择从高地址开始拷贝,而其他情况下选择从低地址开始拷贝。

下面是我自己写的一个memmove实现函数:

void *my_memmove(void *dst, const void *src, int count)
{if(NULL == dst || NULL == src || count <= 0){return NULL;}char *tmp_dst = (char *)dst;char *tmp_src = (char *)src;if((tmp_src < tmp_dst) && (tmp_dst <= (tmp_src+count-1))){tmp_src = tmp_src+count-1;tmp_dst = tmp_dst+count-1;while(count--)   //从高地址开始拷贝{*tmp_dst-- = *tmp_src--;    }}else{while(count--)   //从低地址开始拷贝{*tmp_dst++ = *tmp_src++;}}return dst;
}

综上,如果你在拷贝内存数据的时候不确定源区域和目标区域内存是否重合,最好还是使用memmove函数进行拷贝,以保证结果的正确性。

最后,再讲一讲memcpy函数的特点。
阅读标准C库memcpy的源码,你会发现memcpy函数内部会根据你要拷贝的字节数来选择不同的处理流程。

void *
memcpy (dstpp, srcpp, len)void *dstpp;const void *srcpp;size_t len;
{unsigned long int dstp = (long int) dstpp;unsigned long int srcp = (long int) srcpp;/* Copy from the beginning to the end.  *//* If there not too few bytes to copy, use word copy.  */if (len >= OP_T_THRES){/* Copy just a few bytes to make DSTP aligned.  */len -= (-dstp) % OPSIZ;BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);/* Copy whole pages from SRCP to DSTP by virtual address manipulation,as much as possible.  */PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);/* Copy from SRCP to DSTP taking advantage of the known alignment ofDSTP.  Number of bytes remaining is put in the third argument,i.e. in LEN.  This number may vary from machine to machine.  */WORD_COPY_FWD (dstp, srcp, len, len);/* Fall out and copy the tail.  */}/* There are just a few bytes to copy.  Use byte memory operations.  */BYTE_COPY_FWD (dstp, srcp, len);return dstpp;
}

分析:如果拷贝的字节数比较小,就按字节(一个字节一个字节)进行拷贝;如果拷贝的字节数较大,那就先拷贝几个字节使DSTP对齐;然后尽可能通过虚拟地址操作将整个页面(虚拟内存页)从SRCP复制到DSTP。接着利用已知的DSTP对齐,从SRCP复制到DSTP。剩下的字节数放在第三个参数中,即LEN中。这个数字可能因机器而异。最后,还剩余少数字节,我们按字节拷贝即可。

总结

1、memcpy拷贝的结果可能不正确;memmove可以保证结果是正确的。在不确定内存是否重合的情况下优先考虑memmove。
2、一般情况下,memcpy由于实现比memmove简单(内部逻辑判断没那么多)效率会高一点。

C语言的memcpy和memmove相关推荐

  1. C语言:memcpy、memmove等函数的了解,使用以及模拟实现

    C语言:memcpy.memmove等函数的了解,使用以及实现 1.memcpy函数的介绍,使用,以及实现 2.memmove函数的介绍,使用,以及实现 1.memcpy函数的介绍,使用,以及实现 1 ...

  2. C语言学习笔记---数据拷贝函数memcpy()和memmove()函数

      在C语言中拷贝字符串的时候通常可以使用strcpy()函数和strncpy()函数,这两个函数是专门针对字符串拷贝的.如果想要拷贝其他类型数组的话,可以使用memcpy()和memmove()函数 ...

  3. 【C语言】memcmp、memcpy、memmove、memset、memchr函数详解

    目录 一.综述 二.介绍 1.memcmp 2.memcpy 3.memmove 4.memset 5.memchr 一.综述 memcmp.memcpy.memmove.memset.memchr都 ...

  4. C语言 -- string.h中函数功能详解与手动实现 - 02(常用函数memcpy、memmove、strcpy、strdup、strcat、strtok...)

    内容预览 3.5.搬迁类型 --- 函数功能详细说明 :将内存空间中内容移动.复制到另一内存空间 3.6.搬迁类型 --- 函数功能测试与手动实现 3.6.1.memcpy.memccpy 3.6.2 ...

  5. 如何用C语言实现各种字符函数和字符串函数strstr、memcpy、memmove、strlen、strcpy、strcmp、strcat

    用C语言模拟实现字符函数与字符串函数 strstr.memcpy.memmove.strlen.strcpy.strcmp.strcat 若使用本文相关代码,还请动手点个赞!!! #define _C ...

  6. memcpy、memmove、memset、memchr、memcmp、strstr详解

    第一部分 综述 memcpy.memmove.memset.memchr.memcmp都是C语言中的库函数,在头文件string.h中.memcpy和memmove的作用是拷贝一定长度的内存的内容,m ...

  7. memcpy和memmove的区别以及内存重叠问题

    memcpy和memmove的区别以及内存重叠问题 转自:https://www.codecomeon.com/posts/89/ 区别 memcpy() 和 memmove() 都是C语言中的库函数 ...

  8. memcpy、memmove、memcmp、memset函数的使用说明和模拟实现

    在前面的文章中,我已经对字符串函数进行了详细的介绍和模拟实现,今天,我来讲解另一类函数----------内存函数. 这里写目录标题 memcpy函数 memmove函数 memcmp函数 memse ...

  9. C语言之memcpy()函数

    昨天被问了个很基础的C语言的问题. 写出u8 * memcpy(u8 * src, u8 * dst, size_t len)的定义. 比较紧张,以为要考虑很多东西:于是,将很多乱七八糟的情况考虑了下 ...

最新文章

  1. VS生成时复制文件到指定目录
  2. 【职场】是什么让女性在计算机史上“隐身”了?
  3. 成教计算机专业,成教计算机专业毕业.docx
  4. # 2019-2020.3 《java程序设计》第一周学习总结
  5. P1516-青蛙的约会【扩欧,同余方程】
  6. java centertoscreen_java screen的配置详解及注意事项
  7. [Transformer]SPViT:Pruning Self-attentions into Convolutional Layers in Single Path
  8. 逻辑结构的四种基本关系
  9. 梨都飞雪 2021-05-21
  10. 智能相机与工业相机_使用智能手机相机后如何移动到专用相机
  11. MaxENT完整操作
  12. springboot企业人力资源管理系统毕业设计源码291816
  13. 用python实现生成验证码图片
  14. cmd窗口执行cnpm报错记录:FullyQualifiedErrorId : UnauthorizedAccess或者因为在此系统上禁止运行脚本。有关详细信息,请参阅https。。
  15. php stortm 老是闪退,pr加载界面闪退的原因是什么?
  16. 两种方法配置yum仓库
  17. 2022淘宝天猫年货节超级红包攻略
  18. python 因子分析 权重计算方法_【万矿新品】因子研究利器——WindAlpha
  19. 2016计算机微课作品,2016年微课最佳制作工具,你知道吗?
  20. wordpress上一款不错的音乐播放器-Hermit

热门文章

  1. 设计公司的高端logo设计
  2. 一、一个月学习java基础路线以及时间安排
  3. SpringCloud商城day07 商品搜索-2021-10-12
  4. Win10 环境通过gcc手动编译配置boost库 for LibreCAD
  5. 【构建PB级准实时分析引擎】 -- azkaban、airflow、dolphinscheduler、quartz、xxl-job 、oozie调度方案评测
  6. 基于Android的图片分享软件
  7. 为什么Relu会导致死亡节点
  8. 超级干货 :一文读懂大数据计算框架与平台(升级版)
  9. python fileinput_Python中fileinput模块
  10. 委托代理机构申请专利怎么做?