【回味C】函数

来源:互联网 发布:tomcat nginx 哪个快 编辑:程序博客网 时间:2024/05/16 18:58

事实上,C语言并没有要求函数的定义必须放置在调用点之前。
函数声明,使得编译器可以先对函数进行概要浏览,而函数的完整定义以后再给出。
函数声明类似于函数定义的第一行,不同之处是在其结尾处有分号。
double average(double a, double b) ;

在C语言中,实际参数是通过值传递的。

在数组声明中使用关键字static。

int sum_array( int a[static 3] , int n)
这样使用static不会对程序的行为有任何影响。static的存在只不过是一个“提示”,C编译器可以据此生成更快的指令来访问数组。
如果数组参数是多维的,static仅可用于第一纬。

复合字面量

int b[] = {3,9,5,0,3};total = sum_array(b,5);

上面这么写的唯一问题是需要把b作为一个变量声明,并在调用前进行初始化。
如果b不作它用,这样做其实有点浪费。
在C99中,可使用复合字面量来避免该问题。如下:
total = sum_array ( (int []){3,9,5,0,3} , 5);

程序终止

main函数中,省略函数的返回类型在C99中是不合法的。
main函数返回额值是状态码。如果程序正常,main函数应该返回0;为了表示程序异常终止,main函数应该返回非0的值。

exit函数

exit(0);
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);

return函数和exit函数之间的差异是:不管哪个函数调用exit函数都会导致程序终止,return语句仅当由main函数调用时才会导致程序终止。
一些程序员只使用exit函数,以便更容易定位程序中的全部退出点。

递归

如果函数调用它本身,那么此函数就是递归的。
有些编程语言极度的依赖递归,而有些编程语言甚至不允许使用递归。C语言位于中间。

为了防止无限递归,所有递归函数都需要某些类型的终止条件。

经典案例:快速排序算法。

==========================================

Q:C语言是否允许函数定义嵌套呢?
A:不允许。这个限制可以使得编译器简单化。

Q:为什么编译器允许函数名不跟着圆括号?
A:编译器把不跟圆括号的函数名看成是指向函数的指针。指向函数的指针有合法的应用,所以编译器不能自动假定函数名不带圆括号是错误的。

Q:函数声明double average();这种做法合法吗?
A:合法。在经典C中,这是唯一允许的一种声明格式。我们采用的函数原型格式是包含参数信息的,这是C89的新特性。旧式的函数声明虽然还允许使用,但现在已逐渐废弃了。

Q:为什么有的程序员在函数原型中故意省略参数名字?
A:出于防御目的。如果恰有一个宏的名字和参数一样,预处理时参数的名字会被替换,从而导致相应的原型被破坏。多人协作尤为危险。

Q;如果几个函数具有相同的返回类型,是否可以合并?
A:可以合并。void print_pun(void),print_count(int n)
但是这种方式会试的代码混乱。不建议。

Q:如果指定一维数组形式参数的长度,会发生什么?
A:double inner_product(double v[3], double w[3])
除了注明inner_product函数的参数应该是长度为3的数组以外,不会有其他好处。编译器也不会检查参数实际上的长度是否为3,所以不会增加安全性。事实上,还可能会误导,暗示只能把长度为3的数组传递给inner_product函数,但是实际上可以传递任意长度的数组。

Q:如果函数f1调用了函数f2,函数f2调用了函数f1,合法吗?
A:合法。但是必须确保函数f1和f2最终都可以终止!

原创粉丝点击