strcpy/memcpy/memmove的实现

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);

他们的作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。



第一种情况下,拷贝重叠的区域不会出现问题,内容均可以正确的被拷贝。
第二种情况下,问题出现在右边的两个字节,这两个字节的原来的内容首先就被覆盖了而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。实际上,memcpy只是memmove的一个子集


memmove在copy两个有重叠区域的内存时可以保证copy的正确,而memcopy就不行了,

但memcopy比memmove的速度要快一些,如:
char s[] = "1234567890";
char* p1 = s;
char* p2 = s+2;
memcpy(p2, p1, 5)与memmove(p2, p1, 5)的结果就可能是不同的,memmove()可以将p1的头5个字符"12345"正确拷贝至p2,而memcpy()的结果就不一定正确了。

 

1.memmove
函数原型:void*memmove(void*dest, constvoid*source, size_t count)
返回值说明:返回指向dest的void *指针
参数说明:dest,source分别为目标串和源串的首地址。count为要移动的字符的个数
函数说明:memmove用于从source拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。 可以拿它拷贝任何数据类型的对象。
2
.memcpy
函数原型:void*memcpy(void*dest, constvoid*source, size_t count);
返回值说明:返回指向dest的void *指针,可以拿它拷贝任何数据类型的对象。
函数说明:memcpy功能和memmove相同,但是memcpy中dest和source中的区域不能重叠,否则会出现未知结果。

 

3.strcpy

原型:extern char *strcpy(char *dest,char *src);

功能:把src所指由NULL结束的字符串复制到dest所指的数组中。

说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串,返回指向dest的指针。

 

其实在strcpy的实现比较多,但思想是一致的,一般用C来实现,但是memcpy和memmove这样的函数可能是用汇编实现的,并且充分利用块拷贝的思想,不会单字节单字节的拷贝。所以效率strcpy<memcpy.memmove一般由于要判断内存是否重合,效率也会较memcpy低些。

 

 

strcpy

/********字符串的拷贝*****/

 char* strcpy(char*dst,constchar*src)
{
     assert((src!=0)&&(dst!=0));//not null
     char*cp = dst;
     while(*cp++=*src++) ;
     return cp;
}

 

 

memcpy

/****  @brief 以字节的方式直接拷贝

*库中实现是以汇编实现,

*其实可以直接调用strncat函数

* **/

void*memcpy(void*dst,void*src,size_t n)

{

   assert((src!=0)&&(dst!=0)&&(n>0));//not null

   char*dp = (char*)dst;

   char*sp = (char*)src;

   while(n--)

        *(dp++) =*(sp++);

   return dst;

}

memove

 

void *memmove(void *dst,const void *src,int n)

{

     assert((src!=0)&&(dst!=0)&&(n>0));//not null 
     char *dp = (char *)dst;
     char *sp = (char *)src;
          //非重叠
     //dp < sp
     //dp > (sp+n)
     if(sp>dp||(sp+n)<dp)
     {
          while(n--)
              *(dp++) = *(sp++); 
      }else if(sp<dp)//重叠 (此时条件 sp<dp<(sp+n))如果sp==dp则快速的返回
      {//反向拷贝
           sp += n;
           dp += n;
           while(n--)
           *(--dp) = *(--sp);
       }
       return dst;
}

 

补充:

memset
原型:extern void *memset(void *buffer, int
c, int count);
用法:#include
<string.h>
功能:把buffer所指内存区域的前count个字节设置成字符c。
说明:返回指向buffer的指针。用来对一段内存空间全部设置为某个字符。

举例:char
a[100];memset(a, '\0', sizeof(a));

memset可以方便的清空一个结构类型的变量或数组。

如:
struct
sample_struct
{
char  csName[16];
int  iSeq;
int 
iType;
};

对于变量
struct sample_strcut
stTest;

一般情况下,清空stTest的方法:
stTest.csName[0]='\0';
stTest.iSeq=0;
stTest.iType=0;

用memset就非常方便:
memset(&stTest,0,sizeof(struct
sample_struct));

如果是数组:
struct sample_struct 
TEST[10];

memset(TEST,0,sizeof(struct sample_struct)*10);
posted @ 2013-04-11 19:43  ~风~  阅读(333)  评论(0编辑  收藏  举报