memcpy与memmove的区别

来源:互联网 发布:爱的算法免费下载 编辑:程序博客网 时间:2024/05/17 01:33

memcpy和memmove的区别与实现

区别:两个函数都是进行n字节内存内容的拷贝,入口参数和返回参数也都一样,可是这两个函数在内部实现上是有一定区别的,这主要是因为dest内存区域和src内存区域可能有一下四种不同的情况,注意count的影响:

memcpy和memmove的区别与实现

从图中(点击查看全文才能看到图)可以看出,src的内存区域和dest的内存区域相对位置和重叠关系有四种情况,memcpy没有考虑重叠的情况,而memmove考虑到了全部情况,因此memcpy函数的时候可能出现意向不到的结果。

以下是测试它们相同点和区别的程序:

#include <string.h>

int main(void)

{

     char src[]="abcdefghijklmnopqrstuvwxyz";

     char *dest=src+5;

         memcpy(dest,src,8);//case 1,dest>src and overlap,the output is:abcdeabcnopqrstuvwxyz

     //memmove(dest,src,8);//case 1,dest>src and overlap,the output is:abcdefghnopqrstuvwxyz

        // memcpy(dest,src+7,8);//case 2,src>dest and overlap,the output is: hijklmnonopqrstuvwxyz

     // memmove(dest,src+7,8);//case 2,src>dest and overlap,the output is:hijklmnonopqrstuvwxyz

       //memcpy(dest,src,3);//case 3,dest>src+count, nonoverlap,the output is:abcijklmnopqrstuvwxyz

    //memmove(dest,src,3);//case 3,dest>src+count, nonoverlap,the output is:abcijklmnopqrstuvwxyz

      //memcpy(dest,src+10,3);//case 4,src>dest+count and nonoverlap,the output is:klmijklmnopqrstuvwxyz

   //memmove(dest,src+10,3);//case 4,src>dest+count and nonoverlap,the output is:klmijklmnopqrstuvwxyz

    printf("\nThe result is:\n%s",dest);

       return 0;

}

从输出可以看出,这两个函数只有在情况1时不同,主要是因为memcpy没有考虑重叠时的情况,导致src内存并不是原来的内容,而在运行过程中被修改过了。可以看出,使用memmove更具通用性,但是运行速度会慢一点。

这两个函数的实现:

void *memcpy(void *src,void *dest,size_t count)

{

      void *pret=dest;

      while(count--)

          *dest++=*src++;

     return pret;

}

 

void *memmove(void *src,void *dest,size_t count)

{

     void *pret=dest;

      if(src<dest+count)//case 1,copy backward prevent from modifying source data before copy.

      {

            src=src+count-1;

            dest=dest+count-1;

            while(count--)

                     *dest--=*src--;

      }

      else

      {

                while(count--)

                          *dest++=*src++;

      }

    return pret;

}

 

 

 

memcpy()和memmove()都是C语言中的库函数,在头文件string.h中,其原型分别如下:
 

void *memcpy(void *dst, const void *src, size_t count);
void *memmove(void *dst, const void *src, size_t count);

 
它们都是从src所指向的内存中复制count个字节到dst所指内存中,并返回dst的值。当源内存区域和目标内存区域无交叉时,两者的结果是一样的,但如果有交叉呢?先看下图:
 

图的上半部分为源内存区域在目标内存区域右边,下半部分为源内存区域在目标区域左边,源内存区域和目标内存区域都有交叉。

memcpy()是从src的起始部分开始复制,所以虽然第一种情况下没有问题,但如果遇到第二种情况,则会发生错误,如图所示,后两个字节在被复制前已经被覆盖掉了。而memmove()则由于采用了不同的复制机制,所以可以正确处理第二种情况。

VS.NET2003中所附源码如下(有删):

 

void * __cdecl 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 * __cdecl memmove (void * dst, const void * src, size_t count)
{
        void * ret = dst;

        if (dst <= src || (char *)dst >= ((char *)src + count)) {
                

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

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

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

        return(ret);
}

 

memmove和memcpy

1.memmove

函数原型:void *memmove(void *dest, const void *source, size_t count)

返回值说明:返回指向dest的void *指针

参数说明:dest,source分别为目标串和源串的首地址。count为要移动的字符的个数

函数说明:memmove用于从source拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。

 

2.memcpy

 

函数原型:void *memcpy(void *dest, const void *source, size_t count);

返回值说明:返回指向dest的void *指针

函数说明:memcpy功能和memmove相同,但是memcpy中dest和source中的区域不能重叠,否则会出现未知结果。

 

3.两者区别

  函数memcpy()   从source  指向的区域向dest指向的区域复制count个字符,如果两数组重叠,不定义该函数的行为。  
  而memmove(),如果两函数重叠,赋值仍正确进行。

  memcpy函数假设要复制的内存区域不存在重叠,如果你能确保你进行复制操作的的内存区域没有任何重叠,可以直接用memcpy;  
  如果你不能保证是否有重叠,为了确保复制的正确性,你必须用memmove。

 memcpy的效率会比memmove高一些,如果还不明白的话可以看一些两者的实现:

1 0
原创粉丝点击