memmove和memcpy区别

memcpy()和memmove()都是c语言的库函数(头文件保护#include <string.h>),作用是拷贝一定长度内存的内容。它们唯一的区别是当内存发生局部重叠时,memmove可以保证拷贝正确,memcpy拷贝的结果是未定义的(取决于编译平台内部对memcpy的优化处理)。函数声明如下:

void * memmove(void * dst, void * src, size_t count)
void * memcpy(void * dst, void * src, size_t count)

dst:目的地址
     src:源地址
     count:拷贝的字节数

Memcpy的实现代码如下:

     可以看到,memcpy内部实现只是单纯的进行地址内容的赋值操作,并没有对重叠区域进行处理。这就会导致到dst和src的地址存在重叠时,拷贝异常。

重叠区域主要分为两种情况,dst地址高于src地址和dst地址低于src地址,下面对这两种情况分别介绍:
1, dst地址低于src地址
     见下图,当dst地址低于src地址时,拷贝src地址开始count个字节到dst地址中,不会存在拷贝覆盖的情况,拷贝正常。

2, dst地址高于src地址
     dst地址高于src地址又可以分为两种情况,dst-src >= ncount和dst-src < ncount。
     2.1,dst-src >= ncount

     当dst与src的地址差大于等于ncount时,从src拷贝ncount个字节到dst地址中,也不会存在地址重叠情况,拷贝正常。

2.2 dst-src < ncount

     如图所示,当dst地址高于src地址,且重叠区域在ncount范围内时,src第一次拷贝src1到dst1时,覆盖了src4,导致后面再将src4拷贝到dst4时,并不是原有的src4值,此种地址重叠情况,会导致拷贝结果不正确。

再看memmove的实现:

     对于我们上述分析的情况1和情况2.1,memmove的处理和memcpy是一样的,但是对于2.2的地址重叠情况,memmove使用了一个else分支处理,处理逻辑也很简单,对于src和dst都是从高地址到低地址遍历拷贝,这样就避免了高地址的覆盖情况。

我们以下面这个例子进行实例验证:

void * mymemcpy(void * dst, void * src, size_t count)
{void * ret = dst;while (count--){*(char*)dst = *(char*)src;dst = (char *)dst + 1;src = (char *)src + 1;}return(ret);}int main()
{char a[8] = "abcdefg";memcpy(&a[1], &a[0], 4);std::cout << "memcpy a = " << a << std::endl;strcpy_s(a, sizeof("abcdefg"), "abcdefg");mymemcpy(&a[1], &a[0], 4);std::cout << "mymemcpy a = " << a << std::endl;strcpy_s(a, sizeof("abcdefg"), "abcdefg");memmove(&a[1], &a[0], 4);     std::cout << "memmove a = " << a << std::endl;system("pause");return 0;
}

输出结果如图:

     可以看到使用内置的memcpy的输出结果和memmove结果一样,但是使用我们自己实现的mymemcpy,却是输出了正确的结果(正确是指:memcpy逻辑本应输出的结果),我使用的编译器是vs2015,在VC6.0编译环境下也是一样的输出结果,这是由于memcpy是一个由编译器实现的函数,编译器内部对它进行了优化处理,导致对重叠区域的地址拷贝会出现未定义结果。
     查阅资料发现有很多人都说memcpy性能远高于memmove,我在windows平台,vs2015环境下测试,两者性能几乎无差别,所以在此环境下,可以直接使用memmove,也避免了考虑使用memcpy带来的重叠区域的未定义现象。

memmove和memcpy区别相关推荐

  1. memmove和memcpy

    1.memmove 函数原型:void *memmove(void *dest, const void *source, size_t count) 返回值说明:返回指向dest的void *指针 参 ...

  2. 手撕内存拷贝函数 memmove、memcpy

    做题家系列 -- 手撕内存拷贝函数 memmove.memcpy memcpy 函数原型 实现思路 手撕代码 面试注意要点 memmove 函数原型 实现思路 手撕代码 面试注意要点 总结 memcp ...

  3. memmove, memcpy 的mem魔法

    1.如果是在相同的数据结构中,对原有的数据结构进行缩减或者交叉数据的复制,根据源码;memmove 是避免了内存交叉的复制 2.而memcpy 的使用 就不考虑复制时的内存交叉的问题 请看下面的代码就 ...

  4. memmove、memcpy和memccpy简介

    memmove.memcpy和memccpy三个函数都是内存的拷贝,从一个缓冲区拷贝到另一个缓冲区. memmove(void *dest,void*src,int count) memcpy(voi ...

  5. c语言strcpy两字符串长度不同,C语言 strcpy和memcpy区别详细介绍

    C语言 strcpy和memcpy区别详细介绍 PS:初学算法,开始刷leetcode,Rotate array的预备知识(写的代码Time Limit Exceed难过)于是百度高效算法,本篇作为预 ...

  6. memmove 和 memcpy的区别

    memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下: void *memcpy(void *dst, const void ...

  7. C/C++ memmove与memcpy的区别及实现

    1.与字符串函数strcpy区别: memcpy与memmove都是对内存进行拷贝可以拷贝任何内容,而strcpy仅是对字符串进行操作. memcpy与memmove拷贝多少是通过其第三个参数进行控制 ...

  8. memcpy()和memmove()函数之间区别

    void* memcpy(void* dest,void* source,unsigned count); memcpy是把source 指向的对象中的n个字符拷贝到dest所指向的对象中,返回指向结 ...

  9. memcpy和memmove函数的区别

    文章目录 前言 memcpy函数 memmove函数 memcmp函数 前言 c语言<string.h>库里面有很多的字符函数,比如memcpy,memmove,memcmp等,这些函数是 ...

最新文章

  1. NVIDIA Jarvis:一个GPU加速对话人工智能应用的框架
  2. windows环境下C语言socket编程
  3. tensorflow和keras的关系
  4. 记一次 JAVA 的内存泄露分析 1
  5. JQuery 实现表格数据行上移与下移效果
  6. cadence学习笔记(2)-PCB封装库制作
  7. matlab图例使用技巧
  8. matlab学生作业代写,代做dataframe留学生作业、matlab编程代写代做、代做matlab实验作业、matlab作业报告帮写...
  9. 路由懒加载import和require用法的区别
  10. Nginx简单配置转发
  11. 【python作业】编写一个函数,由实参传来一个字符串,统计此字符串中字母和数字的个数,在主函数中输入字符串并输出上述的结果。
  12. 【android studio】注册广播监测网络(附加gif和菊花进度条)
  13. 风光储互补系统直流微电网simulink仿真模型 光伏系统通过boost电路升压并入母线,采用扰动观察法实现最大功率跟踪控制
  14. 摄像头的镜头的几个知识点
  15. c语言符号深度理解和再认识
  16. 字符编码 编码转换 乱码
  17. 哈夫曼树(霍夫曼树)-详解
  18. ecognition-易康软件相关操作文档和视频
  19. 39-Figma-APP套样机方法
  20. excel填充空格技巧

热门文章

  1. 写一个人社工作年终总结
  2. 多项式拟合lm_sklearn之多项式回归
  3. LaTeX 变量用正体
  4. slice和splice区别
  5. GO和KEGG富集分析详细步骤
  6. 前端开发想要高薪,看这篇文章就足够了
  7. python建模与仿真控制系统_清华大学出版社-图书详情-《MATLAB控制系统设计与仿真》...
  8. 教你微信扫一扫的正确打开方式
  9. 【docker】拉取一个基础镜像然后制作自己的镜像并复用
  10. php和js调试,JS调试使用详解