核心摘要(一句话概括)
return:用于函数内部,表示从当前函数返回,并将控制权交还给调用该函数的函数。exit():用于程序的任何地方,表示终止整个程序,并将控制权交还给操作系统。
详细对比
为了更清晰地理解,我们通过一个表格和几个场景来深入探讨。

功能与作用域
| 特性 | return |
exit() |
|---|---|---|
| 作用域 | 函数级别 | 程序级别 |
| 功能 | 立即终止当前函数的执行。 将一个值(可选)返回给函数的调用者。 |
立即终止整个程序的执行。 将一个状态码( int 类型)返回给操作系统。 |
| 调用位置 | 只能出现在函数内部。 | 可以出现在程序的任何地方(函数内、main 函数内、甚至全局作用域)。 |
| 返回对象 | 返回给函数调用者。 | 返回给操作系统。 |
| 标准头文件 | C 语言关键字,无需包含头文件。 | 需要包含 <stdlib.h> 头文件。 |
return 的详细用法
return 是 C 语言的关键字,它的行为取决于它出现在哪个函数中。
a) 在普通函数中
当 return 出现在一个普通函数(非 main 函数)中时,它只会终止该函数的执行,并将程序控制权交还给调用它的函数。
示例:

#include <stdio.h>
// 定义一个函数,该函数执行一些操作后返回
int add(int a, int b) {
printf("Inside add(): 正在计算 %d + %d\n", a, b);
int result = a + b;
printf("Inside add(): 计算完成,准备返回结果 %d\n", result);
return result; // 终止 add 函数,并将 result 的值返回给调用者
}
int main() {
printf("Inside main(): 准备调用 add() 函数\n");
int sum = add(5, 3); // add 函数执行完毕,返回值 8 被赋给 sum
printf("Inside main(): 从 add() 函数返回,得到结果 %d\n", sum);
printf("Inside main(): 程序继续执行...\n");
return 0; // 终止 main 函数,程序正常结束
}
输出:
Inside main(): 准备调用 add() 函数
Inside add(): 正在计算 5 + 3
Inside add(): 计算完成,准备返回结果 8
Inside main(): 从 add() 函数返回,得到结果 8
Inside main(): 程序继续执行...
在这个例子中,add 函数中的 return 只结束了 add 函数本身,main 函数继续执行。
b) 在 main 函数中
当 return 出现在 main 函数中时,它有两个作用:
- 终止
main函数的执行。 - 由于
main是程序的入口,终止main也就意味着整个程序结束,这个return的值会被作为程序的退出状态码返回给操作系统。
约定:
return 0;:表示程序成功完成。return 非0值;:通常表示程序遇到了错误或异常。
示例:
#include <stdio.h>
int main() {
printf("程序开始运行...\n");
// 模拟一个错误情况
printf("发生了一个致命错误!\n");
return 1; // 程序以错误状态码 1 退出
// 这行代码之后的代码永远不会被执行
printf("这行代码不会打印,\n");
}
exit() 的详细用法
exit() 函数定义在 <stdlib.h> 中,它的作用是“粗暴”地、立即地终止整个程序,无论它在哪里被调用。
a) exit() 的参数
exit() 接受一个 int 类型的参数,这个参数被称为退出状态码,其约定与 main 函数的 return 值相同:
exit(0);或exit(EXIT_SUCCESS);:表示程序成功完成。(EXIT_SUCCESS是<stdlib.h>中定义的宏,值为 0)exit(1);或exit(EXIT_FAILURE);:表示程序失败。(EXIT_FAILURE是<stdlib.h>中定义的宏,通常值为 1)
b) atexit() 注册的函数
exit() 在终止程序前,会执行所有通过 atexit() 函数注册的函数,这些函数的执行顺序与它们注册的顺序相反(类似栈的“后进先出”原则),这通常用于执行一些清理工作,比如关闭文件、释放内存等。
示例:
#include <stdio.h>
#include <stdlib.h> // 必须包含此头文件才能使用 exit() 和 atexit()
// 清理函数1
void cleanup1() {
printf("执行清理函数1: 关闭数据库连接,\n");
}
// 清理函数2
void cleanup2() {
printf("执行清理函数2: 释放临时内存,\n");
}
int main() {
printf("程序开始运行...\n");
// 注册清理函数
// 注册顺序是 cleanup1 -> cleanup2
atexit(cleanup1);
atexit(cleanup2);
printf("程序正常执行中...\n");
printf("现在调用 exit(0) 来终止程序,\n");
exit(0); // 终止整个程序,并执行已注册的清理函数
// 这行代码之后的代码永远不会被执行
printf("这行代码不会打印,\n");
return 0;
}
输出:
程序开始运行...
程序正常执行中...
现在调用 exit(0) 来终止程序。
执行清理函数2: 释放临时内存。
执行清理函数1: 关闭数据库连接。
注意清理函数的执行顺序是 cleanup2 在前,cleanup1 在后。
关键区别与何时使用
| 场景 | 应该使用 | 原因 |
|---|---|---|
从一个非 main 函数中返回,并希望调用者继续执行 |
return |
return 只退出当前函数,逻辑清晰,符合函数设计的初衷。 |
在 main 函数中结束程序 |
return (推荐) 或 exit(0) |
两者效果几乎一样。return 更符合 C 语言的惯例,直接明了。 |
在程序的任何地方(非 main 函数)需要立即终止整个程序 |
exit() |
在初始化函数中发现致命配置错误,无法继续,此时直接 exit() 退出程序是最直接的方式。 |
| 需要进行程序级别的清理工作(如关闭文件、释放资源) | exit() + atexit() |
atexit 提供了一个标准化的、可靠的机制来确保程序退出前执行必要的清理代码。 |
| 需要从深度嵌套的函数中直接退出程序 | exit() |
如果多层函数调用,用 return 逐层返回会非常繁琐且容易出错。exit() 可以一步到位。 |
一个重要的注意事项:return vs exit() 在 main 函数中的区别
在 main 函数中,return 0; 和 exit(0); 在绝大多数情况下是等价的,它们都会导致程序正常终止,并将退出状态码 0 返回给操作系统。
唯一的、但非常重要的区别在于:
return:只会执行main函数局部作用域中的对象(如局部变量)的析构函数(在 C++ 中)。exit():会执行全局作用域和静态局部作用域中对象的析构函数(在 C++ 中),以及所有通过atexit()注册的函数。
在纯 C 语言中,这个区别主要体现在 atexit() 的调用上。main 函数中的 return 也会触发 atexit() 注册的函数执行,所以通常没有区别,但在 C++ 中,这个区别至关重要。
C 语言示例:
#include <stdio.h>
#include <stdlib.h>
void my_cleanup() {
printf("atexit 注册的函数被调用,\n");
}
int main() {
atexit(my_cleanup);
printf("main 函数即将结束...\n");
// 以下两种方式都会调用 my_cleanup
// return 0;
exit(0);
printf("这行不会执行,\n");
}
无论用 return 还是 exit,输出都是一样的:
main 函数即将结束...
atexit 注册的函数被调用。
| 特性 | return |
exit() |
|---|---|---|
| 核心思想 | 从函数返回 | 退出程序 |
| 控制流 | 返回给调用者 | 返回给操作系统 |
| 使用场景 | 函数设计、正常流程控制 | 错误处理、紧急终止、程序清理 |
| 记忆口诀 | Return from a function. | Exit the whole program. |
理解 return 和 exit() 的区别是写出结构清晰、逻辑正确的 C 程序的基础。return 用于函数间的跳转,而 exit 用于程序的终结。
