函数设计
两大巨头:返回值,参数
C 语言中:两种传递方式:值传递与指针传递
C++中:值传递,指针传递,引用传递
1. 参数的规则
参数的书写要完整
void SetNum(int width, int height);
void fun(void)//无参数的类型
如果参数是指针,且仅做输入用,应该在类型前加const,防止该指针在函数体内被意外的修改(输入参数&&输出参数)
如果输入参数以值传递的方式传递对象,则用(const& )方式来传递,可以省去临时对象的构造与析构过程,提高效率。
避免函数中有太多参数
2. 返回值的规则
不要省略返回值的类型:c语言中,凡是不加返回值的函数,一律按照整型处理,c++中不允许有这种情况发生,如果没有返回值,那么声明为void 类型。
函数的名字与返回值在语义上不能冲突,但是:违反这条规则的典型代表getchar
char c;
c = getchar();
if(c == EOF)
原型:
int getchar(void), char 类型的取值范围为【-128,127】,如果宏EOF的值在这个范围之外,那么if 语句就不起作用了。Why???
答:在正常情况下,getchar 的确返回单个字符,但是getchar 碰到文件结束或者发生读错误时,它必须返回一个EOF,为了区别正常的字符,只好将EOF 定义为-1,所以返回值就成int 型。
有时函数原本不需要返回值,但是为了增加灵活性:支持链式表达式
char* strcpy(char *strDest, char *strSrc);
char str[20];
int len = strlen( strcpy(str,”hello”) );
如果函数的返回值是一个对象,有些场合用引用传递替换值传递可以提高效率,但是有些场合只能用“值传递”而不能用引用传递
1. 函数内部实现的规则
在函数的入口处和出口处进行严格把关
入口处:assert 函数来检查参数
出口处:对return 语句的正确性和效率进行检查。
注意!!!!!!
不要轻视return 语句,它很危险!!!
return 语句不能返回指向栈内存的指针或者引用,因为该内存在函数体结束时被自动销毁。
结果是乱码
要搞清楚是返回的是“值”,“指针”,“引用”;
如果return 语句返回的是一个对象,要考虑return语句的效率,
函数的功能要单一,不要设计多用途的函数
函数的规模要小,尽量控制在50行代码之内
尽量避免函数带有记忆功能,相同的输入应当产生相同的输出,带有记忆功能的函数,其行为可能是不可预测的,因为它的行为可能取决于某种记忆状态,这样的函数既不容易理解,又不容易维护,函数的static 局部变量是函数的“记忆”存储器,尽量少使用static 局部变量。
不仅要检查输入参数的有效性,而且还要检查通过其他途径进入函数体内的变量的有效性,如全局变量,文件句柄。
???????????????什么是文件句柄??
特点:方便对文件的搜寻与隐藏
重要性:对于打开文件是唯一的识别依据。
答:在文件I/O输出中,要从一个文件中读取数据,应用程序首先要调用操作系统函数并传送文件名,并选择一个到该文件的路径来打开文件,该函数取回一个顺序号,即文件句柄(file handle),该文件句柄是打开文件唯一的标识依据,要从文件中读取一块数据,应用程序需要调用函数readfile ,并将文件句柄在内存中的地址和要拷贝的字节数传给操作系统,当完成任务后,并通过调用系统函数来关闭该文件。
6.5 使用断言(assert)
程序一般分为Debug 版本和Release 版本,Debug 版本用于内部调试,Release版本用来发放给客户使用,assert 是仅在Debug 版本里面起作用的宏,用于检查“不应该发生的情况”。
使用断言捕捉不应该发生的非法情况,不要混淆非法情况与错误情况之间的区别,错误情况是一定存在的并要做出处理的。
在函数的入口处,使用断言对参数进行检查