一、函数的意义及特性
1、C程序的执行是从 main 函数开始的,如是在 main函数中调用其他子函数,在调用后流程返回到 main 函数,在 main 函数中结束整个程序的运行。
2、所有函数都是平行的,即在定义函数时是分别进行的,是互相独立的。一个函数并不从属于另一个函数,即函数不能嵌套定义。函数间可以互相调用,但不能调用 main函数。main 函数是系统调用的。
3、从用户使用的角度看,函数有两种:(1)标准库函数 (2)用户自定义函数。
二、函数的一般形式
注意:在形参表中,每个参数的数据类型必须单独给出;形参与实参个数相同,类型匹配。
1、函数的调用
函数封装可以提高代码复用性。
如果返回值无类型,无参数,用void。
函数调用:printStars();
注意:(1)主调函数(被调函数);应用被调函数时,被调函数要放在主调函数之前。
(2)有返回值类型的函数中若无返回值(不return),结果不确定。
(3)return会终止当前函数,返回到主调函数中去。
(4)C语言中不写返回值类型,默认为int型。
例如:实现素数的函数封装及调用。
(1)封装
(2)调用
2、注意
(1)被调函数中发现错误,不能通知主调函数具体错误。可以返回-1(return -1)。
(2)在形参向实参传参时,只能进行值传递。实参是形参的复制品,两者拥有不同的内存空间;无法在被调函数中修改主调函数被定义的实参和数值。
例如:结果仍为10。
(3)被调函数有2个或者2个以上时,默认传参次序为自右向左。禁止在实参中进行++、--操作,结果不确定。
例如:结果为20,10。
三、函数调用在编译器中的底层逻辑
1、 函数允许嵌套调用。
主函数逐条执行程序,直到遇到被调函数;先向栈中入栈要回来的地址(称为保护现场),之后PC(program counter)指向被调函数的入口地址,当被调函数执行结束后,出栈刚才放的回来的地址(称为恢复现场),跳回主函数。
栈:FILO先进后出(入栈、出栈)。“栈区”是有限的,在Linux下栈区空间在8M左右,在windows下栈区空间只有1M;栈区中可存入定义的任何变量、函数形参。
例如:
2、内存分成五个区
栈区、堆区、字符串常量区、静态(全局)区和代码区。
四、函数的递归调用
分为间接调用和直接调用,自己调自己。无条件递归调用,导致栈区空间消耗殆尽,程序崩溃(不是死循环)。
例如:利用递归从1加到100。
例如:实现汉诺塔。返回值达到几千亿个,但入栈出栈在64个左右,因此不会使程序崩溃。