淘宝面试题:
已知strcpy函数的原型是:
char *strcpy(char *dst, const char *src);
1:实现strcpy函数;
2:解释为什么返回char *;
3: 假如考虑dst和src内存重叠情况,strcpy如何实现;
原始代码:
char *my_strcpy(char *dst,const char *src) { char *ret = dst; while(*src != '\0') { *dst++ = *src++; } *dst = '\0'; return ret; }
改进代码:
char *my_strcpy(char *dst,const char *src)//1 { assert(dst != NULL && src != NULL);//2 char *ret = dst;//3 while((*dst++ = *src++) != '\0'); return ret; } //1:使用const,保证源字符串不被改变 //2:检查指针的有效性,增强代码的健壮性,使用NULL(拼写错误,编译器容易检查出来),而非0,增强程序的可维护性 //3:保存目标字符串的地址,程序结束时返回 //返回char*:使函数能够支持链式表达式:如:int lenth = strlen(strcpy(dst,src));
char *my_memmove(char *dst,const char *src,size_t lenth) { assert(dst != NULL && src != NULL); char *ret = dst; if(dst<src || dst>=src+lenth)//正常情况,从低地址往高地址依次拷贝 { while(lenth--) { *dst++ = *src++; } } else//内存重叠情况,从高地址往低地址拷贝 { dst = dst + lenth - 1;//要存放元素的最后一个位置 src = src + lenth - 1;//最后一个要拷贝的元素的地址 while(lenth--) { *dst-- = *src--; } } return ret; } //考虑内存重叠----my_strcpy char *my_strcpy(char *dst,const char*src) { assert(dst != NULL && src != NULL); char *ret = dst; my_memmove(dst,src,strlen(src)+1); return ret; }
查看memmove函数原型:
void *my_memmove(void *dst,const void *src,size_t lenth)
实现如下:
void *my_memmove(void *dst,const void *src,size_t lenth) { assert(dst != NULL && src != NULL); void *ret = dst; char *dst1;//保存目标数组:强制转化类型后的地址 char *src1;// 保存源数组:强制转化类型后的地址 if((unsigned char *)dst<(unsigned char *)src ||(unsigned char *)dst>=((unsigned char *)src+lenth)) { dst1 = (char *)dst; src1 = (char *)src; while(lenth--) { *dst1++ = *src1++; } } else { dst1 = (char *)dst + lenth - 1;//问题????????? src1 = (char *)src + lenth - 1; while(lenth--) { *dst1-- = *src1--; } } return ret; }
问题:
dst1 = (char *)dst + lenth - 1;不应该指向最后一个空间之后,再强制类型转化么,如
int a[2] a+2-1指向最后一个空间,(char*)a+2-1并未指向最后一个空间,可是改成
(char*)(dst + lenth - 1);由于dst类型是void,无法加lenth,,那该怎么解决呢????
希望得到你们的解答,谢谢