我们学习了函数的嵌套调用,可以在函数中调用函数。那么,如果在一个函数中,调用自己这个函数,那么,这个执行过程称为:函数递归调用。这个函数也称为:递归函数。程序测试例子:
深入学习,可以交个朋友,工人人人号:韦凯峰linux编程学堂
程序运行结果如下:
深入学习,可以交个朋友,工人人人号:韦凯峰linux编程学堂
在这个测试例子中,我们定义了func函数,在func函数中又调用了func函数自己;所以,这个过程称为:递归调用。
我们知道,在程序的执行过程中,碰到函数调用的时候,就跳转到函数定义的函数体中执行,那么,函数的递归调用。就是函数又跳转到自己定义的函数体中运行;那么,我们分析上面例子中,函数的递归调用执行过程:
(1) 程序从main函数开始,执行到func(3);代码,就跳转到func函数中执行;
(2) 执行func(3);代码,就是把实参3数值,传递给形参变量x;然后,执行x–;形参变量x的值变为2;接着执行if(x <= 0)判断,由于变量x的值等于2,大于0,所以,没有执行return语句,继续执行:
printf("x = %dn", x);
func(x);
此时,输出调试信息,然后,执行func(x);代码,就是在func函数中调用func函数,就是递归调用,由于x变量值为2,相当于执行func(2);代码。
(3) 执行func(2);代码,把实参2数值传递个形参变量x,然后,执行x–;形参变量x的值变为1;接着执行if(x <= 0)判断,由于变量x的值等于1,大于0,所以,没有执行return语句,继续执行:
printf("x = %dn", x);
func(x);
此时,输出调试信息,然后,执行func(x);代码,递归调用,由于x变量值为1,相当于执行func(1);代码。
(4) 执行func(1);代码,把实参1数值传递个形参变量x,然后,执行x–;形参变量x的值变为0;接着执行if(x <= 0)判断,由于变量x的值等于0,所以,执行return语句,结束func(1)函数调用。
(5) 结束func(1)函数调用,就返回到func(2)的调用,func(2)函数执行结束之后,返回到func(3)函数的调用;
(6) 最后,func(3)函数调用结束,就返回到main函数中继续执行。
那么,这个函数递归调用的过程,可以总结成如下图:
深入学习,可以交个朋友,工人人人号:韦凯峰linux编程学堂
可以看到,函数的调用调用流程如下:
func(3) à func(2) à func(1)
那么,当调用到func(1)的时候,进入func函数,执行x–语句,变量x的值变为0,然后,判断if(x <= 0)语句,由于 x<=0 表达式的值为真,所以,执行return语句,结束func(1)函数的调用。
结束func(1)函数的调用之后,返回到func(2)函数,然后,执行:
printf("call end, x = %dn", x);
输出 call end, x = 2 语句,就是说明返回到func(2)函数的调用中。然后,结束func(2)函数的调用之后,返回到func(3)函数。结束func(3)函数调用之后,就返回到man函数中。
注意:递归函数就是重复调用自己的函数。那么,函数不可以无限地调用自己,否则,出现函数栈调用异常。所以,递归调用的函数,应该有结束递归调用的时候。例如上面测试的例子中,func函数递归调用,会判断变量x,如果 if(x <= 0)判断成立,则执行return语句,退出函数运行,不再递归调用func函数。这样,就结束了函数的递归调用。