exit和return

退出和返回
退出状态(exit status)
函数返回一个被称为退出状态的值. 退出状态可以由return 来指定statement, 否则函数的
退出状态是函数最后一个执行命令的退出状态(0 表示成功,非0 表示出错代码). 退出状态
(exit status)可以在脚本中由$? 引用. 这个机制使脚本函数也可以像C 函数一样有一个\"
返回值\".
return
终止一个函数.return 命令[1]可选地带一个整数参数,这个整数作为函数的\"返回值\"返回
给调用此函数的脚本,并且这个值也被赋给变量$?.

exit函数和return函数的主要区别是:

1)exit用于在程序运行的过程中随时结束程序,其参数是返回给OS的。也可以这么讲:exit函数是退出应用程序,并将应用程序的一个状态返回给OS,这个状态标识了应用程序的一些运行信息。

main函数结束时也会隐式地调用exit函数,exit函数运行时首先会执行由atexit()函数登记的函数,然后会做一些自身的清理工作,同时刷新所有输出流、关闭所有打开的流并且关闭通过标准I/O函数tmpfile()创建的临时文件。

exit是系统调用级别的,它表示了一个进程的结束,它将删除进程使用的内存空间,同时把错误信息返回父进程。通常情况:exit(0)表示程序正常, exit(1)和exit(-1)表示程序异常退出,exit(2)表示系统找不到指定的文件。

 2)return是语言级别的,它表示了调用堆栈的返回;return是返回函数值并退出函数,通常0为正常退出,非0为非正常退出,请注意,如果是在主函数main, 自然也就结束当前进程了(也就是说,在main()里面,你可以用return n,也能够直接用exit(n)来做),如果不是在main函数中,那就是退回上一层调用。在多个进程时,如果有时要检测上个进程是否正常退出,就要用到上个进程的返回值。

 2、进程环境与进程控制

如果exit(int n)是在main函数里被调用的,那么exit(int n)就直接退出程序,并返回一个int型的值。一般在shell下面,运行一个程序,然后使用命令echo $?就能得到该程序的返回值,也就是退出值。理论上exit可以返回小于256的任何整数,返回的不同数值主要是给调用者作不同处理的。

对于单独的进程exit的返回值是返回给操作系统的,但如果是多进程,则是返回给父进程的。父进程里面调用waitpid()等函数得到子进程退出的状态,以便作不同处理。根据相应的返回值来让调用者作出相应的处理。

总的说来,exit(int n)就是当前进程把其控制权返回给调用该子程序的主程序, 括号里的是返回值,告诉调用程序该程序的运行状态。

在C语言中,`exit``return`都用于结束程序或函数的执行,但它们的**作用范围、行为用途**有显著区别。以下是详细对比: --- ### **1. 作用范围不同** | 特性 | `return` | `exit` | |--------------------|-----------------------------------|---------------------------------| | **作用对象** | 仅结束当前函数 | 终止整个程序 | | **调用层级** | 返回调用者(如从`main`返回则结束程序) | 直接终止进程,无论调用层级 | #### **示例说明** ```c #include <stdio.h> #include <stdlib.h> void foo() { printf("Inside foo()\n"); return; // 仅退出foo(),回到main() // exit(0); // 若在此调用,程序直接终止 } int main() { foo(); printf("Back in main()\n"); // 若foo()用return,此行会执行;若用exit,不会执行 return 0; } ``` --- ### **2. 执行流程差异** #### **(1) `return` 的行为** - **函数内返回**:结束当前函数,将控制权交还给调用者。 - **`main` 中的 `return`**: - 返回一个整数值给操作系统(通常`0`表示成功,非零表示错误)。 - 在C中,`main`的`return`会隐式调用`exit`(等价于`exit(返回值)`)。 #### **(2) `exit` 的行为** - **立即终止程序**:无论调用层级多深,直接结束进程。 - **执行清理操作**: - 调用通过`atexit`注册的函数(按注册的逆序执行)。 - 刷新所有输出缓冲区(如`printf`的缓冲区)。 - 关闭所有打开的文件流(如`stdin`、`stdout`)。 - 释放静态/全局变量占用的内存(但动态内存需手动释放)。 #### **关键代码对比** ```c #include <stdio.h> #include <stdlib.h> void cleanup() { printf("Cleanup function called\n"); } int main() { atexit(cleanup); // 注册退出时调用的函数 // 情况1:使用return printf("Using return:\n"); return 0; // 输出Cleanup,然后程序结束 // 情况2:使用exit // printf("Using exit:\n"); // exit(0); // 直接终止,不返回main,但仍输出Cleanup } ``` --- ### **3. 参数与返回值** | 特性 | `return` | `exit` | |--------------------|-----------------------------------|---------------------------------| | **参数类型** | 返回函数声明的类型(如`int`) | 必须为`int`(表示退出状态) | | **返回值用途** | 返回给调用者(如`main`返回OS) | 仅表示程序终止状态(OS可读取) | #### **示例:退出状态** ```c #include <stdlib.h> int main() { // exit(1); // 非零表示错误(可通过echo $?在Shell中查看) return 1; // 等价于exit(1)(仅当在main中时) } ``` --- ### **4. 典型应用场景** #### **(1) `return` 的适用场景** - 函数内部提前退出(如错误处理)。 ```c int divide(int a, int b) { if (b == 0) { return -1; // 错误时提前返回 } return a / b; } ``` - `main` 函数中正常退出(返回状态码给OS)。 #### **(2) `exit` 的适用场景** - 程序遇到不可恢复的错误(如内存分配失败)。 ```c #include <stdlib.h> void critical_error() { fprintf(stderr, "Fatal error!\n"); exit(1); // 直接终止程序 } ``` - 多线程程序中主线程需要终止所有线程。 - 需要确保`atexit`注册的函数被执行(如日志清理)。 --- ### **5. 关键注意事项** #### **(1) 内存泄漏风险** - `exit` **不会**自动释放动态分配的内存(如`malloc`申请的堆内存)。 ```c #include <stdlib.h> void leak_memory() { int *p = malloc(sizeof(int)); exit(0); // 内存泄漏!p未被释放 } ``` - 解决方案:在`atexit`中释放内存,或避免在可能调用`exit`的路径中分配内存。 #### **(2) 与`_Exit`的区别** - `_Exit`(C99引入)是`exit`的轻量级版本: - 不调用`atexit`函数。 - 不刷新缓冲区。 - 仅用于紧急终止(如`abort`的替代)。 #### **(3) 信号处理中的`exit`** - 若程序因信号(如`SIGINT`)终止,默认行为可能类似`exit`,但可通过`signal`或`sigaction`自定义。 --- ### **6. 关键总结** | 问题 | 答案 | |-------------------------------|----------------------------------------------------------------------| | **`return` 的作用** | 结束当前函数,返回控制权给调用者(`main`中返回时等价于`exit`)。 | | **`exit` 的作用** | 立即终止整个程序,执行清理操作(如`atexit`函数)。 | | **何时用 `return`** | 函数内部需要提前退出或`main`中正常结束。 | | **何时用 `exit`** | 遇到致命错误需强制终止程序,或需要确保清理逻辑执行。 | | **内存管理** | `exit` 不会释放动态内存,需手动处理。 | --- ### **扩展问题** #### **Q1: `exit(0)` `exit(1)` 的区别?** - `0` 表示成功,非零值(如`1`)表示错误(具体值可自定义,通常`1`为通用错误码)。 #### **Q2: 为什么`main`中的`return`会调用`exit`?** - C标准规定`main`的`return`等价于调用`exit`,以确保程序终止时的清理行为一致。 #### **Q3: `exit` 会执行静态变量的析构函数吗?** - C语言没有析构函数概念,但会释放静态/全局变量的内存(动态内存需手动释放)。 #### **Q4: 如何在`exit`前强制刷新缓冲区?** - 显式调用`fflush(stdout)`或设置缓冲区为无缓冲模式(`setbuf(stdout, NULL)`)。 #### **Q5: `exit` `_Exit` 的主要区别?** - `exit` 执行清理操作,`_Exit` 直接终止(不调用`atexit`或刷新缓冲区)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值