strcpy,memcpy,内存块重叠
前段时间准备面试,看了一些库函数的实现,在看到memcpy时,发现有处理source和destination所指内存有重叠的情况,而strcpy没有,特别模仿库函数写了这个函数,并进行了测试.以下是具体的source code 和测试结果.
char *strcpy2(char *strDest, const char *strSrc)
{ assert( (strDest!=NULL) && ( strSrc!=NULL)); if ( strDest == strSrc)
return strDest ; char *tempptr = strDest ; while( (*strDest++ = *strSrc++) != '\0') ; return tempptr ; } 这是修改网络上source code得到的一个版本,简洁,完全可以工作.初看觉得在程序内部改变了strDest和strSrc的地址(确实如此),不是太好,而实际上当别的函数调用后strDest和strSrc的地址恢复到调用前,因为调用只是改变参数的副本,程序改变地址指向的内容,而没有改变地址本身.不过更加明了的写法是用两个零时变量来替代,修改后如下:
char *strcpy3(char *strDest, const char *strSrc)
{ assert( (strDest!=NULL) && ( strSrc!=NULL)); if ( strDest == strSrc)
return strDest ; char *pDest = strDest ; char *pSrc =strSrc;
while( (*pDest ++ = *pSrc ++) != '\0'); return strDest; } 和strcpy2相比,增加了一个变量,不过程式更清晰,看个人爱好了.我偏向strcpy3.呵呵.
void memcpy2(void *pDst,const void *pSrc, size_t size)
{ assert(pDst != NULL); assert(pSrc != NULL); //src and dst has a shared area. if((pSrc<pDst) && ((char*)pSrc+size > pDst)) { char *pstrSrc= (char *)pSrc + size -1; char *pstrDst = (char *)pDst + size -1; while(size--) *pstrDst -- = *pstrSrc--; } else { char *pstrSrc= (char *)pSrc ; char *pstrDst = (char *)pDst ; while(size--) *pstrDst++ = *pstrSrc++; }
}
int main()
{
char *pSrc = (char *)malloc(1024);
char *pDst = pSrc+4; strcpy2(pSrc,"12345678910"); strcpy2(pDst,pSrc); //(1) printf("Before memcpy: pSrc =%s pDst =%s\n",pSrc,pDst); memcpy2(pDst,pSrc,strlen(pSrc)*sizeof(char)); printf("After memcpy: pSrc =%s \n pDst =%s\n",pSrc,pDst); return 0; }
测试结果:
1.如果没有注释掉语句(1),执行到词语时,因为pDst覆盖了pSrc的结束符'\0'而陷入死循环,最后访问到不该访问的地址空间而出现debug错误.
2.注释掉语句(1),执行 memcpy2后,pSrc变成"123412345678910########",pDst变成"12345678910####","#"表示乱码,原因也是原有的结束符被覆盖.程序可以结束.
总结:
1.const在特定的情况下并不能保证它所修饰函数参数为只读.
2.在内存块有重叠的情况下,strcpy会崩溃,memcpy不会.
|


paraliu
博客统计信息
热门文章
最新评论
友情链接