前段时间准备面试,看了一些库函数的实现,在看到memcpy时,发现有处理source和destination所指内存有重叠的情况,而strcpy没有,特别模仿库函数写了这个函数,并进行了测试.以下是具体的source code 和测试结果.
char *strcpy2(char *strDest, const char *strSrc)
{
assert( (strDest!=NULL) && ( strSrc!=NULL));
{
assert( (strDest!=NULL) && ( strSrc!=NULL));
if ( strDest == strSrc)
return strDest ;
char *tempptr = strDest ;
while( (*strDest++ = *strSrc++) != '\0')
;
return tempptr ;
}
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));
{
assert( (strDest!=NULL) && ( strSrc!=NULL));
if ( strDest == strSrc)
return strDest ;
char *pDest = strDest ;
return strDest ;
char *pDest = strDest ;
char *pSrc=\'#\'" /> while( (*pDest ++ = *pSrc ++) != '\0');
return strDest;
}
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++;
{
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);
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不会.