strcpy 面试题 高质量C++
2011-01-25 23:29
225 查看
题目:
已知strcpy函数的原型是:
char * strcpy(char * strDest,const char * strSrc);
1.不调用库函数,实现strcpy函数。
2.解释为什么要返回char *。
解说:
1.strcpy的实现代码
char * strcpy(char * strDest,const char * strSrc) { if ((strDest==NULL)||(strSrc==NULL)) //[1] throw "Invalid argument(s)"; //[2] char * strDestCopy=strDest; //[3] while ((*strDest++=*strSrc++)!='/0'); //[4] return strDestCopy; }
错误的做法: [1] (A)不检查指针的有效性,说明答题者不注重代码的健壮性。 (B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。 (C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好处。直接使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。 [2] (A)return new string("Invalid argument(s)" ;,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。 (B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。 [3] (A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。 [4] (A)循环写成while (*strDest++=*strSrc++);,同[1](B)。 (B)循环写成while (*strSrc!='/0') *strDest++=*strSrc++;,说明答题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上'/0'。 2.返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。同样功能的函数,如果能合理地提高的可用性,自然就更加理想。 链式表达式的形式如: int iLength=strlen(strcpy(strA,strB)); 又如: char * strA=strcpy(new char[10],strB); 返回strSrc的原始值是错误的。其一,源字符串肯定是已知的,返回它没有意义。其二,不能支持形如第二例的表达式。其三,为了保护源字符串,形参用const限定strSrc所指的内容,把const char *作为char *返回,类型不符,编译报错。 |
char * __cdecl strcpy(char * dst, const char * src)
{
char * cp = dst;
while( *cp++ = *src++ )
; /* Copy src over dst */
return( dst );
}
from strcat 的代码
微软的代码。 的确是的 strcpy 根本没有考虑异常, 错误,失败的情况。
套用这里某位老兄原来的说法 就是让他直接崩溃,然后找到bug.
但是应该说 你如果面试敢写 上面的代码 就意味着你面试的结束。
可以这样简单的总结:对于一个系统的内部,应该尽可能由调用者保证参数的正确性;而对于系统与系统之间的接口,则实现者必须检查参数的有效性,应该力求作到对于任何输入,自己都不会crash。strcpy()是前者的一个例子。对于后一种情况,考虑系统调用:无论任何参数,os内核绝对没理由crash;再有web server的例子,无论浏览器向server发送了多么不合理的请求,web server都不应该crash
我来补充一点:
内存访问违例,在linux下会导致OS给你发一个sign 11
如果你捕获了这个sign 11并内置机制妥善处理了它(比如,可以使用setjmp/longjmp,或者干脆用C++提供的现成品try-catch),那么程序显然是不会崩溃的:这是正确且唯一正确的做法。
请用GDB打开所有因为内存访问违例导致crash的core,你会发现程序崩溃的原因不是因为内存访问违例,而是没有处理sign 11,从而导致处理流程跑进系统内置的core dump例程之中
sign 11并非唯一可用的手段——如果深入了解过操作系统的话。
如果感觉不能理解的话,请去查查资料,搞明白CPU执行某指令,发现它访问无效内存或除零错、溢出等等发生后,继而发生的一切细节。
我们一直强调程序有bug就让它crash,原因就在于我们有无数的后续手段,可用以保证代码 总体 的稳定。
隐藏错误去严防crash,代码 局部 看来是稳定了——但 总体 质量必定会是一坨屎。
Bjarne Stroustrup特意强调在c++里应当用0,而非NULL。
5.8 Advice [ptr.advice]
[3] Use0 rather than N U L L ; §5.1.1.
你看过c的标准吗?
6.3.2.3 Pointers
3 An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant.55) If a null pointer constant is converted to a
pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal
to a pointer to any object or function.
55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.
相关文章推荐
- 高质量c/c++里的strcpy()
- 高质量c/c++指南面试题
- (C++面试题)请实现strcpy、memcpy函数
- 不调用库函数,实现字符串复制函数char * strcpy(char * dst, const char * src) C/C++软件开发求职面试题 必备考点(二)
- C++常见面试题(二)strcpy实现
- C&C++常见面试题之strcpy
- 【C++程序设计常见面试题】strcpy()和memcpy()的区别?(00)
- C/C++常见笔试面试题-03(高质量编程)
- C/C++程序员应聘常见面试题深入剖析
- c/c++面试题汇总(2)
- c++面试题(网络通信篇)
- C/C++ 笔试、面试题30
- C++经典面试题(5)
- [C++面试] linux C++服务器面试题
- C++常见面试题(一)——关于字符、字符数组、assert()
- c/c++面试题/笔试题
- C/C++面试题
- c++常见面试题30道
- 10-11-C++游戏服务端面试题
- C/C++/C#面试题精选(23)-(25)