0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

memcpy和memmove的区别是什么

汽车电子技术 来源: wenzi嵌入式软件 作者:wenzid 2023-01-20 16:55 次阅读

基本概念阐述

memcpymemmove都是 C 语言的库函数,相比于 strcpystrncpy只能针对于字符类型的数组(),这两个函数可以拷贝其他类型的数组,对于 memcpymemmove的区别是什么呢?这里,在 Linux 里通过 man命令查看两个函数的区别,查询的结果如下所示,首先是 memcpy函数的阐述。

图片

image-20210729214558247

通过上述信息,可以知道,函数原型是:

void *memcpy(void *dest, const void *src, size_t n);

这个函数的功能如上面所说,就是复制src存储区域 n个字节到dest区域,并且srcdest的内存区域不能够重叠。

紧接着来看memmove函数,同样的,来看Linux里的帮助手册:

图片

image-20210729234529864

通过上述信息,可以知道,对于memmove的函数原型是:

void *memmove(void *dest, const void *src, size_t n);

具体函数是什么意思呢?通过上图中的DESCRIPTION可以看到:

memmove() 函数将 n 个字节从内存区域 src 复制到内存区域 dest, 但是相比于memcpy函数不同的是,他的内存区域可能会重叠:复制的过程就好比是将 src 中的字节首先被复制到一个不重叠的临时数组中srcdest中,然后将字节从临时数组复制到 dest

实现 memcpy 和 memmove及原理介绍

关于前面所叙述的内存重叠的情况,会出现哪些问题呢?在论述这个问题之前,我们先来自己实现 memcpy 和 memmove 函数,当然自己实现的大多数情况是没有库实现的那么严谨和完备的。首先是memcpy函数的实现:

void *memcpy(void *dest, const void *src, size_t count)  
{  
    if(dest == NULL || src == NULL || count <= 0)  return NULL;  
    char *d = (char *)dest;  
    char *s = (char *)src;  
    while(count--)  
    {  
        *d++ = *s++;  
    }  
    return dest;  
}

代码很容易理解,就不在这里进行赘述了,其中,有一点也是笔者自己以前容易遗忘的一点,就是函数入口处对参数进行检查,不然会发生意想不到的错误。

接下来就是 memmove函数的实现:

void *memmove(void *dest, const void *src, size_t count)  
{  
    if(dest == NULL || src == NULL || count <= 0)  return NULL;  
    if(dest < src)  
    {  
        char *d = (char *)dest;  
        char *s = (char *)src;  
        while (count--)  
        {  
            *d++ = *s++;  
        }  
    }  
    else  
    {  
        char *d = (char *)dest + count;  
        char *s = (char *)src + count;  
        while (count--)  
        {  
            *--d = *--s;  
        }  
    }      
    return dest;  
}

memmove 函数要相比于 memcpy函数的实现要复杂一点点:分成了目的地址在前还是在后两种情况,如果是目的地址在前,那么就必须将src地址所在的字符串从前往后拷贝,反之,则必须将src所在的字符串从后往前拷贝。

如何解释这一原因呢,我们从一个例子说起,下面是对应的代码:

int main(int argc, char **argv) 
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    my_memcpy(arr + 2, arr, 20);

    for (i = 0; i < 10; i++) 
    {
        printf("%d ", arr[i]);
    }

    return 0;
}

可以看到代码所实现的功能是,将arr数组中12345拷贝到 34567所在的地址中去,按照这样一个思路,因该输出的是:

1 2 1 2 3 4 5 8 9 10

但是程序运行后输出的是:

1 2 1 2 1 2 1 8 9 10

这是为什么呢?笔者这里来图解一下:

图片

image-20210730003005350

首先,将src地址的值赋值给dest,然后指针后移动,继续下一次的赋值,此时数据就发生了变化,如下图所示:

图片

image-20210730003025398

可以看到,此时 3 的位置变成了 1,继续移动指针,也就有了如下的变化:

图片

image-20210730003207597

我们依据此原理,最后再移动三次指针,也就是如下所示的变化:

图片

image-20210730004153026

最终也就得到了上述的结果。

这种情况也就是dest在后,然后src在前的一种情况,如果是从前往后拷贝的话,也就会造成上述的问题,而解决的办法就是从后往前拷贝,具体的过程,也如下图所示:

图片

image-20210730005452356

可见,如果是此时 dest的地址在src的后面,那么就需要从后往前复制,这样才不会导致数据覆盖掉。

额外注意的一点,上文也提到了,就是说,对于 memmove 也不是一概而论的,如果是 dest的地址在前面,那么也还是需要从前往后复制才行。

至此,关于 memmove和 memcpy 的内容就叙述完啦~

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7534

    浏览量

    128852
  • memcpy
    +关注

    关注

    0

    文章

    9

    浏览量

    2790
  • strcpy
    +关注

    关注

    0

    文章

    5

    浏览量

    1168
收藏 人收藏

    评论

    相关推荐

    C语言中memmove函数的使用

    在C语言编程中,内存操作是不可或缺的一部分,而 memmove 函数是其中一个重要的工具。本文将介绍 memmove 函数的应用场景以及提供详细的示例代码,帮助您更好地理解如何使用这个函数。我们将探讨三个主要的应用场景,分别是
    发表于 09-13 09:17 682次阅读

    Memset、Memcpy、Strcpy 的作用和区别(转)

    使用printf("%s\n",dest);时 输出遇到'\0'时停此输出.所以会输出: Hello (4) 三者区别memset主要应用是初始化某个内存空间。memcpy是用于copy源
    发表于 01-19 11:57

    GPU和CPU的区别是什么

    GPU是如何工作的GPU与DSP区别GPU和CPU的区别是什么
    发表于 01-05 06:15

    memcpymemmove有哪些区别

    memcpy指的是什么?memmove有何作用?
    发表于 12-20 06:19

    strcpy和memcpy区别是什么

    –strcpy和memcpy区别?(1)复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。(2)复制的方法不同。strcpy不需要指定
    发表于 12-21 06:40

    求助!如何才能使memcpy完全使用rt_memcpy

    rt_memcpy_v6.o(.text) refers to rt_memcpy_w.o(.text) for __aeabi_memcpy4 rt_memmove_v6.o(.t
    发表于 04-07 09:28

    怎样去解决memcpy aeabi_memcpy aeabi_memcpy4问题呢?

    ) for __aeabi_memcpy4rt_memmove_v6.o(.text) refers to rt_memcpy_v6.o(.text) for __aeabi_memcpyrt_memmove_v6.o(.tex
    发表于 02-08 11:20

    线性光耦与非线性光耦的区别是什么?

    线性光耦与非线性光耦的区别是什么?
    发表于 06-04 14:08 1.4w次阅读

    memcpy怎么用_memcpy用法总结

    memcpy指的是c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
    发表于 11-28 15:56 4.6w次阅读
    <b class='flag-5'>memcpy</b>怎么用_<b class='flag-5'>memcpy</b>用法总结

    C语言模拟实现memcpy函数

    memcpy指的是c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
    的头像 发表于 06-29 17:29 2298次阅读
    C语言模拟实现<b class='flag-5'>memcpy</b>函数

    C语言模拟实现memmove函数

    memmove用于从src拷贝count个字节到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。但复制后src内容会被更改。但是当目标区域与源区域没有重叠则和memcpy
    的头像 发表于 06-29 17:53 1667次阅读
    C语言模拟实现<b class='flag-5'>memmove</b>函数

    memcpy函数实现及其优化

    函数原型void * memcpy ( void * destination, const void * source, size_t num );
    发表于 12-09 14:25 2371次阅读

    鸿蒙系统和安卓的区别是什么

    鸿蒙系统和安卓的区别是什么?前不久,华为正式发布HarmonyOS 2及多款搭载HarmonyOS 2的新产品。许多小伙伴都想试一试鸿蒙系统,那么鸿蒙系统和安卓的区别是什么,下面小编就为大家带来
    的头像 发表于 06-29 09:32 8.2w次阅读

    LED和OLED的区别是什么

    LED和OLED的区别是什么?
    的头像 发表于 01-14 18:30 1.5w次阅读

    C语言库memcpymemmove区别分析

    memcpymemmove都是 C 语言的库函数,相比于 strcpy和 strncpy只能针对于字符类型的数组(),这两个函数可以拷贝其他类型的数组,对于 memcpymemmove
    发表于 09-19 12:19 1178次阅读