对于一个规模较大的程序,为了便于实现和维护,一般将其分为若干个程序模块,每个模块实现一定多功能。在C语言中,由函数实现模块的功能。一个C程序由多个函数构成。
与生活中“接口“例子类似,函数需要有明确的输入、输出规范。
函数定义
返回值类型 函数名(参数列表)
{
…... // 函数体
}
- 返回值类型、函数名、参数列表三部分构成函数原型(函数头),这三部分说明一个函数的名称、输入及输出规范。(好比函数使用说明书)
- 参数列表指明函数执行时需要哪些数据作为输入。
- 返回值类型指明函数运行结果(输出)时什么类型。
- 值传递
- 引用传递
值传递——形式参数有自己的存储空间,值传递只是将实参的值赋值给形参,函数体改变形参,不会影响实参。且退出函数时,形参的存储空间会被销毁。
引用传递——需要在定义形参时,在类型后面加上&。引用传递的形参没有自己的存储空间,其形参可以看做是实参的别名(绰号)。函数体中修改形参实际就是修改实参。
数组作为函数参数
数组名作为函数参数时,形参数组和实参数组共享存储单元。修改形参数组实际就是修改实参数组。原因是*和[]等价。
- 功能不同,函数名相同
- 形参个数不同
- 形参类型不同
形参的名称,形参的传递方式和函数的返回值都不能作为函数重载的条件。
函数的递归调用
C通过运行时堆栈支持递归函数的实现。递归函数就是直接或间接调用自身的函数。
递归实现某种类型的螺旋状的while循环。white循环在循环体每次执行时必须取得某种进展,逐步迫近循环终止条件。递归函数也是如此,它在每次递归调用后必须越来越接近某种限制条件。当递归函数符号这个限制条件,停止递归调用。
一旦你理解了递归,阅读递归函数最容易的方法不是纠缠它的执行过程,而是相信递归函数会顺利完成它的任务。如果你的每个步骤正确,你的限制条件设置正确,并且每次调用时更接近限制条件,递归函数总是能正确完成任务。
能用非递归方法解决且不是很复杂的问题最好不用递归方法解决。
原因:在函数的递归调用过程中,系统要为每一层调用中的变量开辟存储单元,要记住每一层调用后的返回点,要增加许多额外的开销,因此函数的递归调用通常会降低程序的运行效率。
函函数的参数传递方式数的参数传递方式
函数的参函数的参数传递方式数传递方式