6.2 return
return 用于结束当前函数执行,并把控制权交还调用者。它是函数级别最直接、最清晰的跳转方式。
1. 返回值规则
非 void 函数应返回与声明兼容的表达式;void 函数可写 return; 提前结束。把 return 放在分支入口处(卫语句)通常能减少嵌套深度,让主流程更平直。
c
#include <stdbool.h>
bool is_valid_score(int score) {
if (score < 0 || score > 100) {
return false;
}
return true;
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
2. 与对象生存期的关系
return 执行时,当前函数的自动存储期对象会结束生命周期。因此不要返回指向局部对象的指针。
c
int *bad(void) {
int x = 42;
return &x; /* 错误:返回悬垂指针 */
}1
2
3
4
2
3
4
正确做法是返回值本身、由调用者提供存储,或使用动态分配并明确释放责任。
3. main 的返回语义
在宿主环境中,main 返回值会作为进程退出状态交给执行环境。通常约定 0(或 EXIT_SUCCESS)表示成功,非零(或 EXIT_FAILURE)表示失败。把失败原因映射到稳定返回码,能让脚本、CI 和调用链更容易判断执行结果。
c
#include <stdlib.h>
int main(void) {
int ok = 1;
if (!ok) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
4. 非 void 函数的完整返回
除少数特殊入口(如 main)外,非 void 函数若在控制流上到达末尾却没有返回值,行为不符合标准预期。写分支时应确保每条路径都有明确返回,避免把“理论不会走到这里”当作隐式前提。
5. 返回对象值与接口稳定性
返回值不一定只能是标量,返回结构体对象在语义上完全合法,且常能减少输出参数数量。关键在于让返回类型稳定表达“函数产物”,把失败状态通过额外约定(例如状态码、可选对象)清晰区分。只要接口语义明确,return 就不仅是控制流出口,也是模块契约的一部分。