文档章节

memcpy和memmove

r
 ranjiewen
发布于 2016/11/03 23:52
字数 840
阅读 4
收藏 0

变态的命名

      我们在写程序时,一般讲究见到变量的命名,就能让别人基本知道该变量的含义。memcpy内存拷贝,没有问题;memmove,内存移动?错,如果这样理解的话,那么这篇文章你就必须要好好看看了,memmove还是内存拷贝。那么既然memcpy和memmove二者都是内存拷贝,那二者究竟有什么区别呢?

先说memcpy

      你有没有好好的参加过一场C++笔试。让你写出memcpy的实现,这是多么常见的笔试题啊。现在,拿起你的演算纸和笔;是的,是笔和纸,不是让你在你的IDE上写。写不出来?看下面吧:

void *mymemcpy(void *dest, const void *src, size_t count)
{
    assert(dest != NULL && src != NULL);

    char *tmp = (char *)dest;
    char *p = (char *)src;

    while (count--)
    {
        *tmp++ = *p++;
    }
    return dest;
}

memcpy的实现很简单,一般在笔试时,出现写源码的题目,无非就是需要注意以下几点:

  1. 确定函数原型;
  2. 判断参数合法性;
  3. 逻辑实现(考虑各种情况,统称逻辑实现);
  4. 错误处理。

当然了,我的这个没有错误处理,也不需要错误处理。上面,我写出了memcpy的实现源码,实现原理如下图所示:
果冻想 | 一个原创文章分享网站

这样下去,上面的代码会运行的很好,如果出现下面的情况呢?
果冻想 | 一个原创文章分享网站

i、n、k的内存和J、e、l的内存地址重合了,现在再使用上面的代码进行copy时,会出现什么问题呢?你有没有想过这个问题。如果没有,那就现在想想,不急着阅读下面的内容。

然后,我再留一个问题,上面的代码中,为什么都需要将void *转换成char *呢?比如:

char *tmp = (char *)dest;

可以留言回答哦。

再说memmove

memmove也是用来实现内存的直接拷贝的。说起这个命名,我个人觉的多少还是有点坑的。既然memmove也是用来内存数据移动的,那就先来看看memmove的实现源码。

void *mymemmove(void *dest, const void *src, size_t count)
{
    assert(dest != NULL && src != NULL);

    if (dest < src)   //当目的地址小于源地址时,情况一,从源地址的头部开始复制
    {
        char *p = (char *)dest;
        char *q = (char *)src;
        while (count--)
        {
            *p++ = *q++;
        }
    }
    else     //当
    {
        char *p = (char *)dest + count;
        char *q = (char *)src + count;
        while (count--)
        {
            *--p = *--q;
        }
    }

    return dest;
}

从源码看,memmove的确比memcpy复杂一些;再仔细一看,多了些什么?哦,多了一个else分支,而正是这个else分支,就处理了当src和dest的内存重合的问题。

memcpy和memmove的比较

从实现源码中的确能看出一些猫腻,当出现了src和dest的内存有重合的时机时,memmove的处理规则是从后往前进行copy。当然了,重合的问题,需要考虑的以下两种场合。
果冻想 | 一个原创文章分享网站

如图所示,

当出现(1)对应的情况时,即:dest<src; 就需要先从src的头部开始复制;也就是memmove源码中的if分支,这部分源码和memcpy的实现是一致的;

当出现(2)对应的情况时,即:dest>src; 就需要先从src的尾部开始复制,防止出现了覆盖现象。这就是memmove比memcpy多的一个考虑点,所以说,在实际使用时,使用memmove是比memcpy更安全的。

 

本文转载自:http://www.cnblogs.com/ranjiewen/p/5550085.html

r
粉丝 1
博文 203
码字总数 28
作品 0
武汉
程序员
私信 提问
C++:memset memcpy memmove的定义与区别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/BeerBread134/article/details/88606382 一般来说,如以下示例代码所示: 使用memset进行初始化 ,使用memcp...

陶晨毅
03/16
0
0
c memmove和memcpy的实现和区别

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

元禛慎独
2016/09/29
18
0
memcpy和memmove的区别

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

I慕蓝
2016/05/07
0
0
memcpy的内存重叠问题

【注】改编自memmove 和 memcpy的区别。原作者如有不爽,请告知! memcpy是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下: 使用memcpy时,有可能会遇...

zidanzzg
2016/12/27
549
0
memmove() -- 拷贝内存内容

memmove() -- 拷贝内存内容 2007年07月06日 星期五 11:41相关函数: bcopy(), memccpy(), memcpy(), strcpy(), strncpy() 表头文件: #include <string.h> 定义函数: void memmove(void dest,......

小熊猫大暴走
2012/04/11
46
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Cloud 笔记之Spring cloud config client

观察者模式它的数据的变化是被动的。 观察者模式在java中的实现: package com.hxq.springcloud.springcloudconfigclient;import org.springframework.context.ApplicationListener;i...

xiaoxiao_go
13分钟前
2
0
CentOS7.6中安装使用fcitx框架

内容目录 一、为什么要使用fcitx?二、安装fcitx框架三、安装搜狗输入法 一、为什么要使用fcitx? Gnome3桌面自带的输入法框架为ibus,而在使用ibus时会时不时出现卡顿无法输入的现象。 搜狗和...

技术训练营
今天
3
0
《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
今天
7
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
今天
7
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部