C语言递归调用main函数为何会执行后续printf语句
核心原因
对函数调用的逻辑存在认知偏差:函数调用不是一去不回的单向跳转,哪怕调用的是main函数,也完全遵循标准的函数调用/返回规则,递归调用main本质上和递归调用其他普通函数的执行逻辑没有区别。
关键前提说明
- 代码中
i是static修饰的静态局部变量,仅会在第一次进入main函数时初始化一次,存储在全局静态存储区,整个程序运行期间只有一份实例。后续所有递归进入main的流程,访问的都是同一个i,不会重新创建变量副本,也不会重复执行i=5的赋值操作。 - 函数调用的标准执行流程:
执行到函数调用语句时,系统会先把当前调用点下一条要执行的指令地址、寄存器现场等数据压入调用栈保存,之后跳转到被调用函数的入口执行;当被调用函数执行完毕(遇到return或走完函数体所有逻辑),会从栈顶弹出之前保存的返回地址,跳回该地址继续执行调用点之后的代码。
逐次执行流程拆解
初始状态:第一次加载main函数,静态变量i初始值为5
- 第1次进入main:执行
--i后i=4,值非0,满足if条件,执行main()调用:把当前层printf语句的地址压栈,跳转到main函数入口 - 第2次进入main:跳过静态变量初始化逻辑,执行
--i后i=3,值非0,满足if条件,再次调用main():把当前层的printf地址压栈,跳转到main函数入口 - 第3次进入main:执行
--i后i=2,值非0,满足if条件,调用main(),压栈当前层printf地址,跳转到main函数入口 - 第4次进入main:执行
--i后i=1,值非0,满足if条件,调用main(),压栈当前层printf地址,跳转到main函数入口 - 第5次进入main:执行
--i后i=0,不满足if判断条件,直接走到return 0,当前层main执行结束,弹出栈顶保存的返回地址(第4层main里printf的地址),跳回该位置 - 回到第4层main的调用点后续位置:执行
printf("%d", i),此时全局共享的i值为0,输出第一个0;之后第4层main走到return语句,弹出栈顶保存的第3层printf地址,跳回对应位置 - 回到第3层main的调用点后续位置:执行printf,输出第二个0,之后执行return,弹栈回到第2层printf位置
- 回到第2层main的调用点后续位置:执行printf,输出第三个0,之后执行return,弹栈回到第1层printf位置
- 回到第1层main的调用点后续位置:执行printf,输出第四个0,之后执行return,整个程序结束
最终运行输出为连续的四个0,和实际运行结果完全匹配。
内容的提问来源于stack exchange,提问作者saman naz
相关产品推荐
相关产品推荐

