实现strcpy、strncpy、memcopy、memmove

字符串的strcopy函数

char * my_strcpy(char *strDest, const char * strSrc)
{
    assert((strDest != NULL) && (strSrc != NULL));
    //if (strDest == NULL || strSrc == NULL) return NULL;

    //保存目标字符串的首地址
    char *strDestCopy = strDest;
    while ((*strDest++ = *strSrc++) != '\0');

    return strDestCopy;
}

strncpy函数

char * my_strncpy(char *strDest, const char *strSrc, int num)
{
    assert((strDest != NULL) && (strSrc != NULL));
    //if (strDest == NULL || strSrc == NULL) return NULL;

    //保存目标字符串的首地址
    char *strDestcopy = strDest;
    while ((num--)&&(*strDest++ = *strSrc++) != '\0');
    //如果num大于strSrc的字符个数,将自动补'\0'
    if (num > 0)
    {
        while(--num)
        {
            *strDest++ = '\0';
        }
    }
    return strDestcopy;
}

memmove不考虑内存覆盖问题,memcopy考虑内存覆盖问题

void* my_memcpy(void* dst, const void* src, size_t n)  
{  
    char *tmp = (char*)dst;  
    char *s_src = (char*)src;  

    while(n--) {  
        *tmp++ = *s_src++;  
    }  
    return dst;  
}  

以下部分的原文链接:https://blog.csdn.net/z702143700/article/details/47107701

在我之前博客中写过一个内存复制函数memcopy(http://blog.csdn.net/z702143700/article/details/46628149),是根据源码修改而来,但是这个函数包括源码中都没有考虑一个问题,就是当memTo和memFrom有重叠的情况。
今天就根据源码实现memmove函数,感受下底层源码的极致实现。

void* my_memmove(void* dst,const void* src,size_t count)
{
    void* ret = dst;
    //dst <= src表示,如果dst在src的前面,从前往后复制不会覆盖src中还没有复制的内容

    if (dst <= src || (char*)dst >= ((char*)src + count))
    {
        //从前往后复制,则不会出现覆盖src中没有复制的内容
        while(count--)
        {
            *(char*)dst = *(char*)src; //char类型指针,表示一个字节一个字节的复制
            dst = (char*)dst + 1; //移动一个字节
            src = (char*)src + 1;
        }
    }
    else
    {
        //从后往前复制,则不会出现覆盖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;
        }
    }
    //返回dst的头指针,还方便左值操作。
    //如:ptstr = memmove(ptstr,src,count); cout << memmove(ptstr,src,count);
    return ret; 
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

有人认为dst <= src || (char*)dst >= ((char*)src + count)是表示dst和src区域没有重叠的情况,其实是错误的想法。因为这种情况即使重叠也不会影响复制。如下图中上图所示,当dst复制到第4第5字节时已经覆盖了src的开始第1第2字节,但是并不影响复制。
下图则表示的是dst > src || (char*)dst < ((char*)src + count)的情况,从后往前复制也不会影响复制结果。
这里写图片描述

很显然,上面类似源代码的实现存在多次类型转换,所以,它还是可以进行优化的,优化后的代码如下:

void* my_memmove(void* dst,const void* src,size_t count)
{
    assert(NULL !=src && NULL !=dst);
    char* tmpdst = (char*)dst;
    char* tmpsrc = (char*)src;

    if (tmpdst <= tmpsrc || tmpdst >= tmpsrc + count)
    {
        while(count--)
        {
            *tmpdst++ = *tmpsrc++; 
        }
    }
    else
    {
        tmpdst = tmpdst + count - 1;
        tmpsrc = tmpsrc + count - 1;
        while(count--)
        {
            *tmpdst-- = *tmpsrc--;
        }
    }

    return dst; 
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

最后,memcpy在内存没有重复的情况下能够正确复制,若有重叠情况则复制结果错误,但是它的效率比memmove高。所以,在确定没有重复的情况下用memcpy,在不确定是否有内存重复的情况用memmove。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值