头文件:#include <string.h>

memmove() 用来复制内存内容,其原型为:
    void * memmove(void *dest, const void *src, size_t num);

memmove() 与 memcpy() 类似都是用来复制 src 所指的内存内容前 num 个字节到 dest 所指的地址上。不同的是,memmove() 更为灵活,当src 和 dest 所指的内存区域重叠时,memmove() 仍然可以正确的处理,不过执行效率上会比使用 memcpy() 略慢些。

更多介绍请参考 memcpy(),下面给出一个示例:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main ()
  5. {
  6. char str[] = "memmove can be very useful......";
  7. memmove (str+20,str+15,11);
  8. puts (str);
  9. system("pause");
  10. return 0;
  11. }

运行结果:
memmove can be very very useful.

这段代码能够很好的说明内存重叠时的情况:先将内容复制到类似缓冲区的地方,再用缓冲区中的内容覆盖 dest 指向的内存,请看下图。

 
 
 

Memcopy和memmove函数在linux下看了一下两个函数的源码。

两个函数都在头文件string.h中定义,函数原型为:

void * __cdecl memcpy ( void * dst,const void * src,size_t count);

void * __cdecl memmove ( void * dst,const void * src,size_t count);

实现代码如下:

void * __cdecl memcpy ( void * dst,const void * src,size_t count)

{

         void * ret = dst;

         while (count--)

         { // 注意, memcpy函数没有处理dst和src区域是否重叠的问题

                   *(char *)dst = *(char *)src;

                   dst = (char *)dst + 1;

                   src = (char *)src + 1;

         }

         return(ret);

}

void * __cdecl memmove ( void * dst,const void * src,size_t count)

{

void * ret = dst;

         if (dst <= src || (char *)dst >= ((char *)src + count))

         {

                   // 若dst和src区域没有重叠,则从起始处开始逐一拷贝

                   while (count--)

                   {

                            *(char *)dst = *(char *)src;

                            dst = (char *)dst + 1;

                            src = (char *)src + 1;

                   }

         }

         else

         { // 若dst和src 区域交叉,则从尾部开始向起始位置拷贝,这样可以避免数据冲突

                   dst = (char *)dst + count - 1;

                   src = (char *)src + count - 1;

                   while (count--)

                   {

                            *(char *)dst = *(char *)src;

                            dst = (char *)dst - 1;

                            src = (char *)src - 1;

                   }

         }

         return(ret);

}

总结一下:

当src和dst区域没有重叠时,两个函数是完全一样的。木有重叠的条件是: dst <= src || (char *)dst >= ((char *)src + count 。否则,memcpy是不能正常工作的,memmove是可以正常工作的。

memcpy与memmove区别的更多相关文章

  1. [整理]内存重叠之memcpy、memmove

    函数原型: void *memcpy( void *dest, const void *src, size_t count ); void *memmove( void* dest, const vo ...

  2. memcpy与memmove的区别

    在面试中经常会被问道memcpy与memove有什么区别? 整理如下: 其实主要在考C的关键字:restrict C库中有两个函数可以从一个位置把字节复制到另一个位置.在C99标准下,它们的原型如下: ...

  3. C的memset,memcpy,strcpy 的区别 及memset memcpy memmove源码

    extern void *memcpy(void *dest,void *src,unsigned int count);#include <string.h>   功能:由src所指内存 ...

  4. 【VS开发】【C/C++开发】memcpy和memmove的区别

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

  5. memmove和memcpy函数的区别及实现

    一.memmove()和memcpy()函数和strcpy()函数的区别: (1)使用的类型不同,strcpy()函数只对字符串进行操作:memmove()和memcpy()函数对所有类型都适用,为内 ...

  6. memcpy memmove区别和实现

    memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中. 但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开 ...

  7. C语言标准库函数memcpy和memmove的区别以及内存重叠问题处理

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

  8. memcpy、memmove、memset及strcpy函数实现和理解

    memcpy.memmove.memset及strcpy函数实现和理解 关于memcpy memcpy是C和C++ 中的内存拷贝函数,在C中所需的头文件是#include<string.h> ...

  9. 关于memcpy和memmove的一点说明

    今天看到书上降到memcpy和memmove的区别才突然发现原来两者之间有如此区别,以前只知道这两个函数是 实现同样的功能,没有接触到其不同. memcpy和memmove在MSDN的定义如下: 从两 ...

随机推荐

  1. PythonCrawl自学日志(3)

    2016年9月21日09:21:431.爬虫的抓取周期:(1)首先生成初始请求爬第一个url,并指定一个回调函数被称为与下载这些请求的响应.(2)第一个请求执行通过调用 start_requests( ...

  2. wxPython Modal Dialog 模式对话框

    <wxPython in Action>chap 9 笔记 1. Modal Dialog(模式对话框) A modal dialog blocks other widgets from ...

  3. ubuntu find方法

    通用格式:find pathname -options [-print -exec -ok]例子:find / -name filename 再根目录里面搜索文件名为filename的文件find / ...

  4. C#学习笔记---基础入门(二)

    枚举 枚举是被命名的整型常数的集合:枚举类型的变量只有赋值后才能使用:不同枚举中的枚举值可以重名:可以自定义枚举值. enum Playstates {            跑, 跳,下滑,左转,右 ...

  5. 1195: [HNOI2006]最短母串 - BZOJ

    Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串.Input 第一行是一个正整数n(n<=12), ...

  6. scrum敏捷开发

    团队PM:袁佩佩 scrum敏捷开发计划制定: 确定项目实施具体阶段目标 确定项目相关任务分解 确定每日站立会议进行计划 确定项目计划总结日程 确定风险解决方案

  7. log4j示例

    示例代码:此示例从控制台输入日志,设置了输出等级. # # Log4J Settings for log4j 1.2.x (via jakarta-commons-logging) # # The f ...

  8. [转载]ASP.NET MVC 3的分部视图

    1.什么是分部视图,我们应该什么时候应该用? 作为一个对ASP.NET MVC 模型很熟悉的开发者,他们自然想创建一个内容和代码都可以重用的组件,在web 窗体,我们可以创建一个web用户控件或web ...

  9. uva 10051

    将每一个分解为六个两面的 简单地dp 回溯输出路径..... #include <cstdio> #include <cstring> #include <cmath&g ...

  10. Java中堆、栈、常量池分析

    栈用于存储局部变量,包括基本类型的变量(方法语句块内部定义的变量.方法中的形参).引用类型的变量,它们都是存储在各自的方法栈中,随着方法的执行完成而消失: 堆用于存储引用类型变量所指向的对象,包括普通 ...