1.函数的嵌套调用
-
函数定义与调用的基本规则:
- C语言的函数定义是互相平行、独立的,不能嵌套定义,但可以嵌套调用。
- 在调用一个函数的过程中又调用另一个函数,称为函数的嵌套调用。
- 执行函数嵌套调用时,先执行主函数的开头部分,遇到函数调用语句则转去执行被调用函数,执行完被调用函数后再返回主调函数继续执行。
-
示例分析:
- 用弦截法求方程
f(x) = x^3 - 5x^2 + 16x - 80 = 0
的根。 - 该问题通过多个函数来解决,包括
f(x)
函数(代表x
的函数)、xpoint(x1, x2)
函数(求弦与x
轴交点)、root(x1, x2)
函数(求近似根)。 - 在
root
函数中调用xpoint
函数,而xpoint
函数又调用f
函数,形成函数的嵌套调用。 - 程序从
main
函数开始执行,通过输入确保f(x1)
和f(x2)
异号,然后调用root
函数求根,在root
函数中通过循环和条件判断不断逼近根的精确值。
- 用弦截法求方程
2.函数的递归调用
-
递归调用的概念与特点:
- 在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。
- C语言允许函数的递归调用,但应避免无终止的递归调用,需有结束递归过程的条件。
-
示例分析:
- 例8.8用递归方法求
n!
,根据递归公式n! = {1 (n = 0, 1), n * (n - 1)! (n > 1)}
,通过递归调用fac
函数实现。 - 例8.9用递归方法解决汉诺塔问题,将
n
个盘子从A
座移到C
座的过程分解为三步:将A
上n - 1
个盘借助C
座先移到B
座上;把A
座上剩下的一个盘移到C
座上;将n - 1
个盘从B
座借助于A
座移到C
座上。通过hanoi
函数实现递归调用,模拟和尚移盘的过程。
- 例8.8用递归方法求
在C语言中,内存通常被划分为以下几个区域:
- 栈区(Stack):由编译器自动分配和释放,用于存储函数的参数、局部变量等。函数调用时,相关信息被压入栈中,函数执行结束后,这些信息自动被弹出栈并释放内存。
- 堆区(Heap):由程序员手动分配和释放(使用
malloc
、calloc
、realloc
等函数),若不手动释放,程序结束时可能由操作系统回收。堆区用于动态分配内存,例如当程序需要在运行时根据实际情况确定内存大小来存储数据时使用。 - 字符常量区:用于存储字符串常量和字符常量。这些常量在程序运行期间存在,通常不可修改。
- 静态区(Static):用于存储全局变量和静态变量。全局变量在程序开始时分配内存,在程序结束时释放;静态变量在函数内部使用
static
关键字声明,其生存期从程序开始一直到程序结束。 - 代码区:存储程序的二进制代码。程序在运行时,CPU从代码区读取指令并执行。