
一起动脑筋 · 先看一个小故事
女孩请机器人做午餐,机器人做到一半先去煮水。煮完后,它得记得回来继续哪一步。
把过程摊开来看
- 主任务准备午餐
- 子任务煮水
- 子任务结束返回
- 主任务接着准备午餐
函数调用另一个函数时,调用者会等待这次调用的结果,然后继续。
把“待会儿回来做什么”写在任务卡上,就能理解为什么返回位置需要被记住。
01函数可以调用另一个函数吗?
当然可以:
int doubleValue(int x) {
return x * 2;
}
int addDouble(int a, int b) {
return doubleValue(a) + doubleValue(b);
}
addDouble 在执行过程中又调用了 doubleValue。
02控制流去了哪里?
正在执行 addDouble→进入 doubleValue→返回 addDouble 继续
函数调用像一次“暂时离开”:先去完成被调用函数,再回来接着执行原来的位置。
03程序怎么知道回来以后从哪里继续?
函数调用的实现需要保存“调用完成后应该继续的位置”等信息。
在常见机器和 ABI 中,这些信息会通过调用约定、寄存器和调用栈等机制配合完成。
04每次调用里的参数一样吗?
int a = doubleValue(3);
int b = doubleValue(10);
两次调用执行同一个函数代码,但各自接收到的参数值不同,因此得到不同结果。
05同一个函数连续调用两次,会互相覆盖吗?
对于普通局部参数和局部变量,每次函数调用都具有自己的调用状态。
第一次调用
x = 3
第二次调用
x = 10
它们不是“同一个 x 同时被改成两个值”。
06函数调用会有成本吗?
通常会有一些调用、传参和返回的开销,但现代编译器有时可以进行内联优化(inlining),把函数调用消除或改写。
你已经知道了什么
- 一个函数可以调用另一个函数。
- 调用时控制流暂时进入被调用函数。
- 函数完成后会回到调用点之后继续。
- 每次调用都有自己的参数和局部状态。
- 底层调用机制常涉及返回位置、寄存器和调用栈,但具体实现由平台决定。
下一篇:什么是调用栈?
轮到你来试一试
煮水函数返回后,午餐函数会从第一行重来吗?
想好了吗?点开看解释
不会,通常从调用之后的位置继续。返回位置让程序知道该接上哪一步。