strcpy实现
常见strcpy实现
一个常见的strcpy实现如下:
1 char *my_strcpy(char *dst, const char *src) 2 { 3 if (dst == nullptr || src == nullptr) // 写成!dst或dst == 0都不推荐 4 return nullptr; 5 6 if (dst == src) // 判断dst和src是否已经指向同一块内存,若是则直接返回 7 return dst; 8 9 char *tmp = dst; 10 while ((*dst++ = *src++) != '\0') // 注意在dst末尾加上'\0' 11 ; 12 13 return tmp; // 在这里可能会不假思索就返回dst,但这样是有问题的,因为dst经过累加后实际已指向'\0'的下一块内存
14 }
针对strcpy还有常见的一个问题就是:为什么要返回char *?
因为要让strcpy支持链式赋值,例如:
strlen(strcpy(new char[20], src));
考虑内存重叠
对于strcpy而言,该函数并没有考虑内存重叠的问题,例如
1 char s[10]="hello"; 2 strcpy(s, s+1); //应返回ello, 3 // strcpy(s+1, s); // 应返回hhello,但实际会报错,因为dst与src重叠了,把'\0'覆盖了
所谓重叠,就是src未处理的部分已经被dst给覆盖了,只有一种情况:src<=dst<=src+strlen(src)。
C函数memcpy自带内存重叠检测功能,下面给出memcpy的实现my_memcpy。
1 char *my_memcpy(char *dst, const char *src, int cnt) 2 { 3 if (dst == nullptr || src == nullptr) 4 return nullptr; 5 6 char *tmp = dst; 7 if (dst >= src && dst <= src + cnt - 1) // 内存重叠,从高地址开始复制 8 { 9 dst = dst + cnt - 1; 10 src = src + cnt - 1; 11 while (cnt--) 12 *dst-- = *src--; 13 } 14 else // 正常情况,从低地址开始复制 15 { 16 while (cnt--) 17 *dst++ = *src++; 18 } 19 20 return tmp; 21 } 22 23 char *my_strcpy(char *dst, const char *src) 24 { 25 if (dst == nullptr || src == nullptr) // 写成!dst或dst == 0都不推荐 26 return nullptr; 27 28 if (dst == src) // 判断dst和src是否已经指向同一块内存,若是则直接返回 29 return dst; 30 31 char *tmp = dst; 32 my_memcpy(dst, src, strlen(src) + 1); // 注意strlen并不会将‘\O’统计在内 33 34 return tmp; 35 }
参考资料