前面讲了一些函数的基本概念,函数不能嵌套定义,但可以进行嵌套调用。并且,还可以进行递归调用,这是因为函数在内存中是存储在栈上的,本身栈就可以进行递归操作。递归的效率在所有实现中是最慢的,但是给程序带来是非常简洁,可读性较强,如果在不严重影响性能的情况下也是可以适当的使用递归函数的。如下图所示,主函数调用a函数,a函数又调用b函数,当b函数执行完返回到a函数,再由a函数返回到主函数main中,整个应用才算结束调用。

C语言基本概念(2)_程序

下面通过代码给出一些有关嵌套调用和递归调用的例子。

C语言基本概念(2)_blank_02

数组元素和数组作为形参和实参时,元素同基本数据类型一样,而数组实际上是传递的一个内存地址。

C语言基本概念(2)_target_03

因为有了函数,有了模块,所以变量的声明就有了作用区间,有些变量声明在任何地方均可使用,有些变量声明只能在一个函数内部使用,有些变量声明只能在某个复合语句中有效。变量使用何种声明方式需要根据程序的需要再加上程序源程序的可读性、函数的通用性等这些情况进行考虑,所以一般情况下,函数内部变量最好不好暴露在外。如下图所示,

C语言基本概念(2)_blank_04

前面我们将变量根据作用域即从空间的角度来分为全局变量和局部变量。另外一种考虑方式,因为变量都是放在内存之上,按照变量存储生命周期可将变量分为静态存储变量和动态存储变量。这个也适合与函数。从现实空间意义,我们通常关注一个变量的数据类型如int/void/float,而从计算机内部实现上来说,每种数据都是需要放在内存的指定位置上。具体有四点,auto(自动),static(静态),寄存器(register),外部(extern)。到C++,还有voilate等。其中auto主要指函数中的局部变量,auto不写为隐含定义,自动存储分配都是在动态空间上。static 局部变量是在编译时赋初值的,只赋值一次,运行时已有初值。反过来说明auto局部变量如果不给初值,它的值是未定的。而对静态局部变量默认给出初值为0或空字符。静态局部变量从存储上是一直存在的,但是从作用域上它是局部变量,因此,其它函数仍然不能访问它。register主要是从效率来考虑,一般使用比较少,特别是现在CPU效率比较高,还要考虑移植性等其它因素。extern主要是针对当前程序文件,用extern来声明外部变量,对本文件程序就是全局变量,如果不想他们使用自己定义的全局变量,可以使用static进行定义。

C语言基本概念(2)_内存_05

变量从作用域来分全局与局部,从存储又分成四种。因为存储关系,变量又可分成变量声明与变量定义。通常extern就是变量声明。这里讨论是变量,但是对函数也可以声明static和extern.也就是将函数区分为内部函数,只能被本文件中被其它函数使用,使用static,而外部函数,使用extern,表明可被外部文件使用,默认都是使用extern的。

C语言基本概念(2)_程序_06