首先声明,起这么一个标题,目的是为了“耸人听闻”,吸引读者。:) 文中的两个函数的缺陷,不是我所发现,只是我认为很有意义,与大家共享。而且,可以了解一个成熟系统的“缺陷”,不是非常让人愉快和兴奋吗?
本文的部分内容引用了林锐的《高质量C++/C编程指南》一书。(建议大家都去读读,尤其我找工作的时候,不少小公司直接使用了书中的C++试题作为笔试题目 :) )
1: printf()
相信大家都使用过,MFC 中的TRACE有同样的问题。printf()的缺陷是不安全性和不可扩展性。
1)关于不安全性,《高质量C++/C编程指南》一书有明确的解释:
【建议6-1-2】尽量不要使用类型和数目不确定的参数。
C标准库函数printf是采用不确定参数的典型代表,其原型为:
int printf(const chat *format[, argument]…);
这种风格的函数在编译时丧失了严格的类型安全检查。int i;
printf("%s",i); // 编译时无法使用严格的类型安全检查。
2)关于不可扩展性,是指它不可以和自定义的类型配合使用。请看以下代码:
int i;
float f;
CStudent student; // 自定义的类型,其中重载了 << 操作符
cout << i << f << student;
printf("%d %f",i,f); // 不能和student配合使用
2. getchar()函数,《高质量C++/C编程指南》一书有明确的解释
1) 【规则6-2-2】函数名字与返回值类型在语义上不可冲突。
违反这条规则的典型代表是C标准库函数getchar。
例如:
char c;
c = getchar();
if (c == EOF)
…
按照getchar名字的意思,将变量c声明为char类型是很自然的事情。但不幸的是getchar的确不是char类型,而是int类型,其原型如下:
int getchar(void);
由于c是char类型,取值范围是[-128,127],如果宏EOF的值在char的取值范围之外,那么if语句将总是失败,这种“危险”人们一般哪里料得到!导致本例错误的责任并不在用户,是函数getchar误导了使用者。
2) 【规则6-2-3】不要将正常值和错误标志混在一起返回。正常值用输出参数获得,而错误标志用return语句返回。
回顾上例,C标准库函数的设计者为什么要将getchar声明为令人迷糊的int类型呢?他会那么傻吗?
在正常情况下,getchar的确返回单个字符。但如果getchar碰到文件结束标志或发生读错误,它必须返回一个标志EOF。为了区别于正常的字符,只好将EOF定义为负数(通常为负1)。因此函数getchar就成了int类型。
我们在实际工作中,经常会碰到上述令人为难的问题。为了避免出现误解,我们应该将正常值和错误标志分开。即:正常值用输出参数获得,而错误标志用return语句返回。
函数getchar可以改写成 BOOL GetChar(char *c);
虽然gechar比GetChar灵活,例如 putchar(getchar()); 但是如果getchar用错了,它的灵活性又有什么用呢?