浅谈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. SeaJS基本开发原则
  2. 设计模式笔记(18)---迭代器模式(行为型)
  3. Spring MVC - 配置Spring MVC
  4. Tornado多进程启动的2种方法
  5. 将数据归一化到任意区间范围的方法
  6. 机器学习入门-文本数据-使用聚类增加文本的标签属性
  7. Ollydbg使用教程学习总结(五)
  8. 读取nas_NAS怎么玩?除了存放小姐姐,它竟然还有这些功能
  9. idea中tomcat服务器的配置
  10. 【redis】Redis简介
  11. 古为今用,宽于待人!记住【识人“五视”】
  12. BZOJ.3990.[SDOI2015]排序(DFS)
  13. 移动app测试的多样性_移动App测试一些崩溃原因及触发崩溃的场景
  14. 创新设计思维---自学报告
  15. Android 字体引入
  16. 高频单词700 (高频指的是组合成其它单词的次数)
  17. 帝国CMS 批量修改信息标题方法
  18. 软加密网上激活解决方案
  19. 基于IAP和USB技术的嵌入式系统应用程序升级
  20. Succeeding At Your Yahoo! Business

热门文章

  1. Istio中流量劫持机制
  2. 淘淘商城——商品搜索功能测试
  3. 小学五年级计算机课含板书设计,小学五年级下册课文丰碑教学设计和板书
  4. if(!a) 括号里面的条件 !表示的是什么意思
  5. php调用微信扫一扫功能,微信JSSDK调用微信扫一扫功能的方法
  6. 【密码学原理与实践】(一)移位密码 附java代码实现
  7. 高中计算机会考可以补考吗,高中会考不及格可以进行补考的,一共能补考多少次...
  8. 已解决NameError: name ‘reload‘ is not defined
  9. 【项目】对身份证、手机号码、银行卡信息进行脱敏处理
  10. 数论四大定理之威尔逊定理