内存函数《memcpy》与《memmove》的原理与实现

本文探讨了内存函数memcpy和memmove的使用,虽然两者都能实现数据拷贝,但memcpy主要处理非重叠内存区域,而memmove则能处理重叠内存区域,确保数据正确性。文章通过代码示例解释了两者的实现和在不同编译器下的行为差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、momcpy

momcpy是内存函数中对于指定空间的数据拷贝到另外一个指定的空间中,并根据数据的长度覆盖其中的内容。

说起来memcpy与strcpy有着很相似的地方,那就是功能的实现上:指定拿取源头数据然后覆盖目的地。

不同的是,memcpy是对于内存中的数据进行操作而strcpy是对于字符串进行操作

接下来可以看下它们的实现代码:

char * strcpy ( char * destination, const char * source, size_t num );

void * memcpy ( void * destination, const void * source, size_t num );

可以看到memcpy与strcpy中对于指针的数据类型规范有着很大不同

strcpy指定只能是传入char类型的数据(也就是字符串),memcpy则是void类型。

这就意味着memcpy可以接受任意类型的数据。

 

 注:即使是拷贝数据也是根据字节数来进行操作,1char==1字节;

这里我贴一下实现代码:

void* memcpy(void* dst, const void* src, size_t n)
{
    if (NULL == dst || NULL == src)
        return NULL;
    void* ret = dst;
    char *dst_ = (char*)dst;
    char *src_ = (char*)src;
    while (n--)                                   
    {
        *dst_++ = *src_++;
    }
    return ret;
}

二、memmove

memmove与memcpy也很相似,甚至在传参上都一样。

这里我放下函数定义:

void * memmove ( void * destination, const void * source, size_t num );

这里会发现C规定的这两个函数是不是有些矛盾?别急往下看

我找了解释专业的文章贴在上面

可以看出memmove除了具有memcpy的功能甚至多了一个:可以处理重叠空间的数据拷贝。

嗯?怎么回事

发现好像memcpy也能实现mememove的功能?

这里说明一下,主要是每个编译器厂商对于memcpy和memmove都有对应的优化,我使用的VS系列对于memcoy和memmove的功能定义是一致的,

但是对于其他(像是gcc)则是分的很明白,重叠空间的数据拷贝就是由memmove实现。

而且重叠拷贝的也会有一种问题:应该从什么方向开始?

第一种:

将输入区间的元素拷贝到输出区间的红色区点域的位置,也就是输出区间的尾部与输入区间发生重叠,也就是dst <= src的情况,这种情况拷贝结果是正确的。

第二种

将输入区间的元素拷贝到输出区间的黑色点区域的位置,也就是输入区间和输出区间完全没有重叠,也就是(char*)dst >= (char*)src + n 的情况,这种情况拷贝结果是正确的

第三种:

将输入区间的元素拷贝到输出区间的绿色点区域的位置,也就是输出区间的头部与输入区间发生重叠,也就是dst > src && (char*)dst < (char*)src + n   的情况,这种情况拷贝结果会出现问题,因为复制输入区间前,它的元素值可能被覆盖,这种情况memmove函数值这样处理的:反向进行复制,也就是src和dst的尾部成了头部,而头部成了尾部,dst = (char*)dst + n - 1;src = (char*)src + n - 1;然后从右向左复制,就变成第一种情况,这种会保证复制结果是正确的.

这里放一下实现代码:

void* memmove(void* dst, const void* src, size_t n)
{
    if (NULL == dst || NULL == src)
        return NULL;
    void* ret = dst;                                   
    char *dst_=(char*)dst;
    char *src_=(char*)src;
    if (dst <= src ||dst_ >= (src_ + n))  //第一种和第二种的情况
    {
        while (n--)                                    //正向进行复制(从头至尾)
        {
          *dst_++=*src_++;   
        }
    }
    else                              //第三种情况             反向进行复制(从尾至头)
    {
        dst_ += n - 1;
        src_ += n - 1;
        while (n--)
        {
           *dst_ -- =*src_ --;
        }
    }
   return ret;
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值