美文网首页程序员
memcpy与memmove的区别

memcpy与memmove的区别

作者: 卡巴拉的树 | 来源:发表于2017-03-18 15:44 被阅读1549次

memcpy和memmove都是C语言的库函数,相比于strcpy和strncpy只能拷贝字符串数组,memcpy与memmove可以拷贝其它类型的数组,但是为什么要同时提供两种方法呢?本文主要就是介绍这两个函数的区别。

首先来看函数原型:

void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
void *memmove(void *s1, const void *s2, size_t n);

这两个函数都是将s2指向位置的n字节数据拷贝到s1指向的位置,区别就在于关键字restrict, memcpy假定两块内存区域没有数据重叠,而memmove没有这个前提条件。如果复制的两个区域存在重叠时使用memcpy,其结果是不可预知的,有可能成功也有可能失败的,所以如果使用了memcpy,程序员自身必须确保两块内存没有重叠部分。

我们来看一组示例:

正常的拷贝

正常情况下,即使内容有重叠,src的内容也可以正确地被拷贝到了dest指向的空间。

内存重叠的拷贝

这种情况下,src的地址小于dest的地址,拷贝前3个字节没问题,但是拷贝第4,5个字节时,原有的内容已经被src拷贝过来的字符覆盖了,所以已经丢失原来src的内容,这很明显就是问题所在。

memcpy的实现##

一般来说,memcpy的实现非常简单,只需要顺序的循环,把字节一个一个从src拷贝到dest就行:

#include <stddef.h> /* size_t */
void *memcpy(void *dest, const void *src, size_t n)
{
    char *dp = dest;
    const char *sp = src;
    while (n--)
        *dp++ = *sp++;
    return dest;
}

memmove的实现##

memmove会对拷贝的数据作检查,确保内存没有覆盖,如果发现会覆盖数据,简单的实现是调转开始拷贝的位置,从尾部开始拷贝:

#include <stddef.h> /* for size_t */
void *memmove(void *dest, const void *src, size_t n)
{
    unsigned char *pd = dest;
    const unsigned char *ps = src;
    if (__np_anyptrlt(ps, pd))
        for (pd += n, ps += n; n--;)
            *--pd = *--ps;
    else
        while(n--)
            *pd++ = *ps++;
    return dest;
}

这里__np_anyptrlt是一个简单的宏,用于结合拷贝的长度检测dest与src的位置,如果dest和src指向同样的对象,且src比dest地址小,就需要从尾部开始拷贝。否则就和memcpy处理相同。
但是实际在C99实现中,是将内容拷贝到临时空间,再拷贝到目标地址中:

#include <stddef.h> /* for size_t */
#include <stdlib.h> /* for memcpy */

void *memmove(void *dest, const void *src, size_t n)
{
    unsigned char tmp[n];
    memcpy(tmp,src,n);
    memcpy(dest,tmp,n);
    return dest;
}

由此可见memcpy的速度比memmove快一点,如果使用者可以确定内存不会重叠,则可以选用memcpy,否则memmove更安全一些。另外一个提示是第三个参数是拷贝的长度,如果你是拷贝10个double类型的数值,要写成sizeof(double)*10,而不仅仅是10。

相关文章

  • memmove 和 memcpy 的区别

    memmove和memcpy都是拷贝,区别是memmove会判断方向,如果有重叠的区域那么memcpy就会有问题 ...

  • memcpy与memmove的区别

    memcpy和memmove都是C语言的库函数,相比于strcpy和strncpy只能拷贝字符串数组,memcpy...

  • memmove与memcpy

    我们知道,分类的方法列表是通过memmove和memcpy加到类的方法列表的前面,而同名的分类方法根据文件的编译顺...

  • memmove 和 memcpy的区别

    memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,...

  • memmove 和 memcpy的区别

      在看Category的源码时碰见了两个C语言函数memmove和memcpy,在string.h中我们可以看见...

  • 不可忽视的memmove与memcpy区别

    同样的服务端程序,在ubunut下面运行正常,在centos7下面会运行出错。出错的原因在于在调用recv,返回值...

  • 总结:头文件cstring函数的用法(original)

    一.复制类(cpy) (1)memcpy 函数原型: 用法:可与用于转移数据 (2)memmove 函数原型: 基...

  • memset, memcpy and memmove

    memset 函数原型 头文件include 功能将dest所指的内存区域的前size个字节的值全部设置为ch指...

  • memcpy memmove 函数

    memcpy函数 函数原型 功能:由src指向地址为起始地址的连续 size个字节的数据复制到以dest指向地址为...

  • memmove和memcpy

    内存移动void *memmove(void *str1, const void *str2, size_t n)...

网友评论

    本文标题:memcpy与memmove的区别

    本文链接:https://www.haomeiwen.com/subject/udbunttx.html