高质量编写strcpy()
《高质量C++编程指南》的作者林锐博士,曾去微软中国研究院面试,而面试官让他写一个简单的strcpy()函数。林博士很惊讶,心想这有什么难的。而半小时后,林博士大汗淋漓地走出了”考场“。
这样一个小不点函数,面试官从三个方面考察:
- 代码风格
- 出错处理
- 算法复杂度分析
由此可见,编写出合格的strcpy()是不容易的,它尤其考验程序员的基本功和思维的严密性。
下面直接给出最终代码,再逐步剖析:
1 | char* strcpy(char* des, const char* src) |
- 参数类型: 将
src
的内容拷贝到des
中,并不会修改src
。所以为了防止误操作改变src
,需要声明为const char*
。- 自赋值: 当
des
与src
相同时,直接返回任意一者。此处的自赋值并不是像实现string
类的赋值函数中的那样必要,但无疑,当两者相同时这样处理更高效。- 检查空指针: 这是绝对必要的一步,不检查会引起崩溃。为什么使用
assert
而不是if
,可见详解if与assert。那么为什么要用两行assert
而不直接assert((dest!=NULL) && (src !=NULL))
?因为前者能定位出错的位置,而后者并不能定位到两个指针中哪个为NULL。- 保存原始des值: des的指向已经更改,不能直接返回。
- 返回值为什么是
char*
: 为了支持链式赋值:int len = strlen(strcpy(des,src));
很多人疑惑为什么不考虑内存重叠(src低于des)的情况,下面是我的猜测:
- strcpy()不同于memcpy(),后者能应对内存重叠是因为它有第三个参数n(开辟的字节数),如果发生内存重叠,则可以从高位往低位拷贝,这个过程必须要用n来计数。而前者没有参数n,只能依靠字符串结束符
'\n'
来判别终点,所以无法从高位往低位拷贝。- 也许某些时候不要考虑太高的容错性,这样会隐藏人为过失,导致最后bug难以溯源。灵活性 != 容错性。
有错误烦请读者指出。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 极简!
评论