getchar 的思考v0.2
为什么地址线要20条?

memcpy还是memmove?

风中纸页 posted @ 2008年7月18日 05:09 in 程序设计 , 1903 阅读
转贴请保留本文作者及文章地址

二话不说,先举例子:

例子1:

 

#include <stdio.h>
#include <STRING.H>

int main(void)
{
    char a[10] = "Hello!" ;
   
    printf("%s\r\n",a);

    memcpy(&a[2], a, 5);

    printf("%s\r\n",a);
   
    return 0;
}

 

例子2:

 

#include <stdio.h>
#include <STRING.H>

int main(void)
{
    char a[10] = "Hello!" ;
   
    printf("%s\r\n",a);

    memmove(&a[2], a, 5);
    printf("%s\r\n",a);
   
    return 0;
}

 

使用gcc 编译

$ gcc -v
Using built-in specs.
Target: i686-pc-cygwin
Configured with: ./configure
Thread model: single
gcc version 4.3.0 (GCC)
 

例子1的结果是:

 

$ ./a.exe
Hello!
HeHeHeH

例子2的结果是:

 

$ ./a.exe
Hello!
HeHello


从这两个简单的例子:我们可以看出memcpy和memmove的基本区别就是:源地址和目的地址是否可以重叠。(其实这个主要和库函数的实现有关)

为了明白这个问题:

我们看看memcpy的源码:

 

 

/* Copy memory to memory until the specified number of bytes
   has been copied.  Overlap is NOT handled correctly.
   Copyright (C) 1991, 1997 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   Contributed by Torbjorn Granlund (tege@sics.se).

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */


#include <string.h>
#include <memcopy.h>
#include <pagecopy.h>

#undef memcpy

void *
memcpy (dstpp, srcpp, len)
     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 whole pages from SRCP to DSTP by virtual address manipulation,
         as much as possible.  */


      PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);

      /* Copy from SRCP to DSTP taking advantage of the known alignment of
         DSTP.  Number of bytes remaining is put in the third argument,
         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;
}
 

 

 

我们来看看memmove的源码:

 

 

/* Copy memory to memory until the specified number of bytes
   has been copied.  Overlap is handled correctly.
   Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   Contributed by Torbjorn Granlund (tege@sics.se).

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */


#include <string.h>
#include <memcopy.h>
#include <pagecopy.h>

/* All this is so that bcopy.c can #include
   this file after defining some things.  */

#ifndef a1
#define a1       dest   /* First arg is DEST.  */
#define a1const
#define a2       src    /* Second arg is SRC.  */
#define a2const  const
#undef memmove
#endif
#if     !defined(RETURN) || !defined(rettype)
#define RETURN(s)        return (s)      /* Return DEST.  */
#define rettype    void *
#endif


rettype
memmove (a1, a2, len)
     a1const void *a1;
     a2const void *a2;
     size_t len;
{
  unsigned long int dstp = (long int) dest;
  unsigned long int srcp = (long int) src;

  /* This test makes the forward copying code be used whenever possible.
     Reduces the working set.  */

  if (dstp - srcp >= len)       /* *Unsigned* compare!  */
    {
      /* 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 whole pages from SRCP to DSTP by virtual address
             manipulation, as much as possible.  */


          PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);

          /* Copy from SRCP to DSTP taking advantage of the known
             alignment of DSTP.  Number of bytes remaining is put
             in the third argument, 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);
    }
  else
    {
      /* Copy from the end to the beginning.  */
      srcp += len;
      dstp += len;

      /* 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_BWD (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 argument, i.e. in LEN.  This number may
             vary from machine to machine.  */


          WORD_COPY_BWD (dstp, srcp, len, len);

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

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

  RETURN (dest);
}
 

一进函数我们“惊喜”的发现了:

 

if (dstp - srcp >= len)

这个对源地址目的地址进行了判断,如果地址没有重叠的话,我们可以看到memcpy和memmove所做的处理几乎完全相同;但在else里面我们看到了我们想要的内容。

基本处理思路:不是从前向后拷贝有可能会把还没有处理的数据会“冲掉”么?那么我们就从最后一个字符开始向前拷贝,这样就不会存在没有数据重叠了吧。。:)

前面提到这个问题和库函数的实现有关: 如果拿VC6.0作为编译器的话,其库的实现memcpy和memmove的结果是一样的。这样处理的原因不明。哪位知道讲解一下或者有代码让我看看都不胜感激!

  • 无匹配
NCERT Term 1 Sample 说:
2022年9月23日 20:22

NCERT have introduced First Term Sample Paper Suggestions for all Languages and Subjects of the Secondary Level 9th Class Students. Every student can download the Term-1 study and learning materials along with sample papers to know about the new exam scheme or question paper pattern of the exam. NCERT Term 1 Sample Paper Class 9The Study materials are very helpful to practice with regular revisions and mock tests.NCERT have introduced First Term Sample Paper Suggestions for all Languages and Subjects of the Secondary Level 9th Class Students.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter