函数
计科中叫:子程序
- 是一个大型程序中的某部分代码,由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代码具备相对的独立性。
- 一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库
C中函数
1. 库函数
2. 自定义函数
自定义函数和库函数一样,有函数名,返回值类型和函数参数。
函数组成
声明和定义
函数声明
- 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。
- 函数的声明一般出现在函数的使用之前。要满足先声明后使用
- 可以先声明后定义
- 函数的声明一般要放在头文件中的。
一般在项目中创建头文件,然后把函数写在头文件中
add.c里面放函数的定义
add.h里面放函数的声明
add.c和add.h称为一个模块
#include
自己定义的头文件用""
原有的头文件用<>
函数定义
函数的定义是指函数的具体实现,交待函数的功能实现。
好函数的特点
1. 高内聚低耦合,否则不易维护
2. 完成功能单一,作为一个程序中的小单元,之后使用时调用即可,不要加入print等
错误示范
数组传参实际上传递的是数组首元素的地址,而不是整个数组
所以在函数内部计算一个函数参数部分的数组的元素个数是不靠谱的
计算数组元素个数应在主程序中
函数递归
程序调用自身的编程技巧称为递归 (recursion)
递归做为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法
它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的优势和劣势
优势
代码简明
劣势
效率低下
容易溢出
若劣势较为明显时,应选择迭代而非递归
递归的主要思考方式在于;把大事化小
递归的两个必要条件
存在限制条件,当满足这个限制条件的时候,递归便不再继续。
每次递归调用之后越来越接近这个限制条件。
常见错误
栈溢出
递归不当时容易申请过多内存导致栈溢出
递归一定要加条件
死递归会导致栈溢出
函数参数
形参和实参
函数调用
传值调用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
传址调用
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
应用举例
1. 想修改参数本身值时需要使用实参(传地址)
2. 无需修改值,仅需获得值可使用形参(不传地址)
在有循环的函数中 return > break
return 0时函数停止运行
break 只能结束循环
嵌套
函数可以嵌套调用(在主程序中相互嵌套),不能嵌套定义(在定义函数时定义)函数是平等的
主程序中可以相互嵌套,函数定义内不能嵌套定义
链式访问
前提条件:
函数有返回值
把一个函数的返回值作为另一个函数的参数
eg. printf()链式访问
最内层的先打印43,后续printf打印前一个嵌套中的输出结果的数字个数
故为43 <- 2 <- 1