C標準庫string.h源碼實現七memcpy/memmove

void *memcpy(void *dst, const void *src, size_t count)
{
    void * ret = dst;

    while (count--) {
        *(char *)dst = *(char *)src;
        dst = (char *)dst + 1;
        src = (char *)src + 1;
    }

    return(ret);
}
void *memcpy(void *dstpp,const void *srcpp,size_t len)
{
  unsigned long int dstp = (long int) dstpp;
  unsigned long int srcp = (long int) srcpp;

  /* Copy from the beginning to the end.  */

  /* If there not too few bytes to copy, use word copy.  */
  if (len >= OP_T_THRES)
    {
      /* Copy just a few bytes to make DSTP aligned.  */
      len -= (-dstp) % OPSIZ;
      BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);

      /* Copy from SRCP to DSTP taking advantage of the known
	 alignment of DSTP.  Number of bytes remaining is put
	 in the third argumnet, i.e. in LEN.  This number may
	 vary from machine to machine.  */

      WORD_COPY_FWD (dstp, srcp, len, len);

      /* Fall out and copy the tail.  */
    }

  /* There are just a few bytes to copy.  Use byte memory operations.  */
  BYTE_COPY_FWD (dstp, srcp, len);

  return dstpp;
}

參考glibc的實現我們最終實現的版本如下:

 memcpy函數有一個問題,如果|dest-src| < count,也就是他們有重疊區域時,該函數不能正常工作,此時要使用memmove

​void *memcpy(void *dest,const void *src,size_t len)
{
    void * ret = dest;

    //dest步進char_len字節後內存對齊
    unsigned char_len = sizeof(unsigned long) - dest % sizeof(unsigned long); 
    char *ch_start = src;//按字節複製,並使內存對齊
    while((char_len>0) && (len >= char_len))
    {
        *(char *)dest = *(char *)src;
        dest = (char *)dest + 1;
        src = (char *)src + 1;
        len--;
    }

    while(len >= sizeof(unsigned long))//按unsigned long大小複製
    {
        *(unsigned long *)dest = *(unsigned long *)src;
        dest = (unsigned long *)dest + sizeof(unsigned long);
        src = (unsigned long *)src + sizeof(unsigned long);
        len -= sizeof(unsigned long);
    }

    while(len-- > 0)  //剩餘部分按字節複製
    {
        *(char *)dest = *(char *)src;
        dest = (char *)dest + 1;
        src = (char *)src + 1;
    }

    return ret;
}

 

 //memmove函數如果區域沒重疊,等效於memcpy函數,否則從src的尾部往頭部的順序執行復制。

void * memmove(void * dst, const void * src, size_t count)
{
    void * ret = dst;

    if (dst <= src || dst >= (src + count)) {/*Non-Overlapping Buffers*/
        while (count--)
            *dst++ = *src++;
    }
    else {
        /*
        * Overlapping Buffers
        * copy from higher addresses to lower addresses
        */
        dst += count - 1;
        src += count - 1;

        while (count--)
            *dst-- = *src--;
    }

    return(ret);
}
​
void *memmove(void *dest,const void *src,size_t len)
{
    void * ret = dest;
    
    if (dest <= src || dest >= (src + count)) {
        return memcpy(dest,src,len);
    }
    
    dest += len - 1;
    src += len - 1;

    unsigned char_len = dest % sizeof(unsigned long);

    char *ch_start = src;//按字節複製,並使內存對齊
    while((char_len > 0) && (len >= char_len) )
    {
        *(char *)dest = *(char *)src;
        dest = (char *)dest - 1;
        src = (char *)src - 1;
        len--;
        char_len--;
    }

    while(len >= sizeof(unsigned long))//按unsigned long大小複製
    {
        *(unsigned long *)dest = *(unsigned long *)src;
        dest = (unsigned long *)dest - sizeof(unsigned long);
        src = (unsigned long *)src - sizeof(unsigned long);
        len -= sizeof(unsigned long);
    }

    while(len-- > 0)  //剩餘部分按字節複製
    {
        *(char *)dest = *(char *)src;
        dest = (char *)dest - 1;
        src = (char *)src - 1;
    }

    return ret;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章