
转:C/C++:memmove、memcpy、strcpy三者的区别
strcpy只能处理字符串;如果拷贝带有特殊字符的串,就只能用memcpy或memmove。memcpy和memmove功能基本上差不多,但是当源串和目标串有Overlap时,memmove可以正确处理,memcpy则不行。
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 * 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);
}  | 
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) ;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiang1013nan/archive/2009/12/26/5073116.aspx
void* mymemcpy(void* pvTo, const char* pvFrom, size_t size)
{
assert((dest != NULL) && (src != NULL));
byte* psTo = (byte*)pvTo;
byte* psFrom = (byte*)pvFrom;
while (size-- > 0)
{
*psTo++ = *psFrom++;
}
return pvTo;
}
memset ,memcpy 和strcpy 的根本区别
2009年10月27日 星期二 上午 10:46
以下内容为网络整理的结果!
它们用处不同,但大部分情况下可以完成相同的要求。
strcpy
原型:extern char *strcpy(char *dest,char *src); 用法:#include  例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串长度(第一个‘\\0’之前)是否超过50位,如超过,则会造成b的内存地址溢出。 memcpy 原型:extern void *memcpy(void *dest, void *src, unsigned int count);用法:#include  举例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),会造成b的内存地址溢出。 memset原型:extern void *memset(void *buffer, int c, int count);用法:#include  举例: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); 对这个问题有疑问,不是对函数的疑问,而是因为没有弄懂mem和str的区别。 mem是一段内存,他的长度,必须你自己记住 str也是一段内存,不过它的长度,你不用记,随时都可以计算出来所以memcpy需要第三个参数,而strcpy不需要 void* memcpy(void* pvTo, const void* pvForm, size_t size) { assert((pvTo!= NULL) && (pvFrom!= NULL));//使用断言防止传递空地址 unsigned char* pbTo = (unsigned char*)pvTo;//防止改变pvTo的地址 unsigned char* pbFrom = (unsigned char*)pvFrom;//防止改变pvFrom的地址 while(size-- > 0) {    *pbTo++ = *pbFrom++; } return pvTo; } char* strcpy(char* pDest, const char* pSrc) { assert((pDest != NULL) && (pSrc != NULL)); char *pTmp = pDest; while ((*pDest++ = *pSrc++) != '\\0')    ; return pTmp; } FeedBack: # re: memcpy与strcpy实现 2008-08-27 20:35 | temp do not forget const      # re: memcpy与strcpy实现 2009-07-23 22:10 | flame //注意数据重叠区的处理。  // |----------|  // |----------|  void *MyMemCopy(void *dest,const void *src,size_t count)  {  char *pDest=static_cast const char *pSrc=static_cast //注意,这里是关键,为什么要这样比较呢?理由何在?  if( pDest>pSrc && pDest for(size_t i=count-1; i>=0; --i)  {  pDest[i]=pSrc[i];  }  }  else  {  for(size_t i=0; i pDest[i]=pSrc[i];  }  }  return pDest;  } //注意数据重叠区的处理。  // |----------|  // |----------|  void *MyMemCopy(void *dest,const void *src,size_t count)  {  char *pDest=static_cast const char *pSrc=static_cast //注意,这里是关键,为什么要这样比较呢?理由何在?  if( pDest>pSrc && pDest for(size_t i=count-1; i>=0; --i)  {  pDest[i]=pSrc[i];  }  }  else  {  for(size_t i=0; i pDest[i]=pSrc[i];  }  }  return pDest;  }
这篇文章里的内容就是对那些想通过自我研究达到学会编程目的的新手们的一些重要建议。 编程老手们:我有什么遗漏吗? 不论你的水平如何,请留下你的想法。
