实现strcpy是一道常见的C++面试题,林锐的《高质量程序设计指南——C/C++语言》给出的实现如下:
char * strcpy(char *dst,const char *src)
{
assert(dst != NULL && src != NULL);
char* address = dst;
while((*dst++ = *src++)!=' ');
return address;
}
这个代码看着简单,一共只有四句,但实际上大有玄机。
第一句assert是对传入的dst和src进行非法检查,确认是否传入的指针为空值。
第二句将dst的地址传到address中,因为之后dst就会递增了。
第三句是一个while循环,将src指向的字符依次赋值给dst,然后检查赋值的字符是否为字符串结束符' ',以此决定是否结束循环。然后个指针各自自增。
之后返回address地址。之所以要return一个char*指针,是为了给这个函数支持链式表达式的操作:int l=strlen(strcpy(strA,strB))。
这个代码实际上仍然有bug,它无法处理dst和src内存重叠的情况,如下图所示:
图中src位于低地址,dst位于高地址,src和dst的字符串存在重叠。此时按照上面的代码,最终会覆盖src字符串自己所属的内存区域导致报错。
C函数自带的memcpy自带内存重叠检测功能,下面给出我实现的my_memcpy:
char * strcpy(char *dst,const char *src)
{
assert(dst != NULL && src != NULL);
char* address = dst;
my_memcpy(dst, src, strlen(src)+1);
return address;
}
char *my_memcpy(char *dst, const char* src, int cnt)
{
assert(dst != NULL && src != NULL);
char *address = dst;
if (dst >= src && dst <= src+cnt-1)
{
//内存重叠,从高地址开始复制
dst = dst + cnt - 1;
src = src + cnt - 1;
while(cnt--)
*dst-- = *src--;
}
else
{
//正常情况,从低地址开始复制
while (cnt--)
*dst++ = *src++;
}
return ret;
}