C语言中递归调用未返回父栈帧却能传值至主函数的疑问
递归实现最小公倍数(LCM)代码的返回值疑问解析
找到的递归LCM代码
#include<stdio.h> int lcm(int a, int b) { static int common = 1; if (common % a == 0 && common % b == 0) { return common; } common++; lcm(a, b); // 递归调用lcm函数 } void main() { int a=5; int b=6; int c= lcm(a,b); printf("\n%d",c); }
疑问点
我理解代码的大部分逻辑,但对lcm函数最后一行的
lcm(a,b);存在疑问:以输入5和2为例,会产生10次递归调用,当触发基准条件执行return common;时,该返回值并未被第9层递归调用保存,却能传递至main函数。我理解使用return lcm(a,b);时的递归值传递逻辑,但不清楚未加return时的传递原理。
问题解析
首先要明确:这段代码的行为属于C语言的未定义行为,并不是什么合法的传递逻辑。
C语言标准规定,具有返回值类型的函数(比如这里的int型lcm函数),如果执行到函数末尾没有显式的return语句,函数的返回值是不确定的。你测试时能拿到正确结果,只是编译器的偶然行为:
- 多数编译器会用特定寄存器来存储函数返回值,当最内层递归执行
return common;时,这个值会被存入该寄存器。 - 外层的递归调用执行完
lcm(a,b);后,没有写return就直接结束,此时返回值寄存器里还残留着内层递归返回的值,所以main函数“碰巧”拿到了正确结果。
但这种行为完全不可靠,换编译器、编译选项甚至代码位置,结果都可能出错,属于错误写法。
正确写法
必须在递归调用处加上return,把下层的返回值逐层传递上来:
// 修正后的递归调用行 return lcm(a, b);
额外bug说明
这段代码还有另一个问题:static int common = 1;中的static变量只会初始化一次。如果多次调用lcm函数,common会保留上一次调用后的数值,导致后续计算结果错误。比如第一次调用lcm(5,2)得到10,第二次调用lcm(2,3)时,common会从11开始递增,而不是重新从1开始,这不符合LCM的计算逻辑。
内容的提问来源于stack exchange,提问作者Aman Nambisan
相关产品推荐
相关产品推荐

