读K&R之幻数、返回值和参数传递

Dennis M. Ritchie

直到不久前,我都不曾认真地了解过C。大学课堂上学习过C++,在那段不长的时间里,学到的东西一直支撑着我对C的认知。等工作五年后,我重新学习C时,发现自己好生浅薄。就在自己还在读《The C Programming Language》的第二章时,网络上传来了Dennis M. Ritchie过世的消息。大师已逝,他所留下的知识将会继续惠泽着后人。我把阅读《The C Programming Language》所作的笔记整理出来,希望更多的人能够学习到Dennis M. Ritchie所建立的知识,这也算是对大师的一种纪念。

关于Magic Number

在程序中使用“幻数”是个坏习惯,它几乎不能提供任何信息。要避免这个问题,就是使用#define指令把符号名定义为一个特定的字符串。这使我想起来了在《深入Java虚拟机》一书中看到的一段话:

例如每个class文件必须是以四个同样的字节开始:魔数0xCAFEBABE。这个魔数的用处是让class文件分析器很容易分辨出某个文件有明显问题而加以拒绝。1

上面的“幻数”与“魔数”应该都是英文术语magic number的翻译,我把它理解成一个有特定意义的数字,这个数字没有名字,没人知道它代表什么意思,因此阅读程序代码的人就可能糊涂。——当然,0xCAFEBABE不会有人去读它,我只是想到了magic number这个词而已。

关于返回值

通常情况下,main函数返回值为0表示正常结束,非0表示出现异常情况或出错结束条件。

那么对于一般函数,返回值有什么约定俗成的规则吗?我想到了 Linux kernel coding style 中的两段话:

Functions can return values of many different kinds, and one of the most common is a value indicating whether the function succeeded or failed. Such a value can be represented as an error-code integer (-Exxx = failure, 0 = success) or a “succeeded” boolean (0 = failure, non-zero = success).

Functions whose return value is the actual result of a computation, rather than an indication of whether the computation succeeded, are not subject to this rule. Generally they indicate failure by returning some out-of-range result. Typical examples would be functions that return pointers; they use NULL or the ERR_PTR mechanism to report failure.

上面的文字按照是否表示执行成功来将返回值分为两大类,前者又区分为需要详细的错误码和只需要成功与否两种情形,后者则是使用NULL或ERR_PTR来标识失败。

关于参数传递

所有函数参数都是“通过值”传递,传递给被调用函数的参数值存放在临时变量中,而不是存放在原来的变量中。因此,被调用函数不能直接修改主调用函数中变量的值,而只能修改其私有的临时副本的值。

如果要让被调用函数能够修改主调用函数的变量,那么调用者需要向被调用函数提供设置值的变量的地址,而被调用函数则需要将对应的参数声明为指针类型,并通过它间接访问变量。

当把数组名作为参数时,传递给函数的值时数组起始元素的位置或地址,–它并不赋值数组元素本身。


参考文献

  1. Bill Venners. 深入Java虚拟机(原书第二版)[M]. 曹晓钢, 蒋靖, 译. 北京:机械工业出版社, 2003.9:32

Leave a comment

Your comment