关于exit() 和 return ()

本文详细解析了C++与C语言中exit与return函数的使用区别,包括它们如何影响程序的执行流程、退出状态以及对象析构等关键信息。文章深入探讨了两者在不同场景下的应用,并提供了实际代码示例进行说明。
exit把控制权交给系统,而return将控制权交给调用函数。

exit()有返回值的,不过返回值传递给操作系统或者说运行环境。 
exit用于在程序运行的过程中随时结束程序,exit的参数是返回给OS的。 
main函数结束时也会隐式地调用exit函数。exit函数运行时首先会执行由atexit()函数登记的函数,然后会做一些自身的清理工作,同时刷新所有输出流、关闭所有打开的流并且关闭通过标准I/O函数tmpfile ()创建的临时文件。 

c++ primer第四版中文版 216页最下方有一句话 
“主函数main不能调用自身” 
但以下程序可以编译成功。
int main(int argc, char** argv) { 
   if(argc==0) 
     return 0; 
     //exit(0);
   else { 

     int rv; 
     rv=main(argc-1, argv); 
     printf("%s\n",argv[argc-1]); 
     return rv; 
   } 
分别将第三行代码换成return 0; 或 exit(0); 从这里面可以看出,使用exit程序直接退出,不能继续执行,而如果用return的话,main函数是作为一个普通的函数进行递归调用的。
     由此,我认为文章开头的句红字是正确的,而以下的一些内容,是我在网上各处搜集,别人的一些解释,留作对比。

要区分c和c++,c++中的main函数不可以递归调用,但是c可以 

在C++中 main函数中的exit和return并不完全一样,比如下面代码 
  
#include <iostream> 
class A 

public: 
     A(){ std::cout << "A constructed\n"; } 
     ~A(){ std::cout << "A destructed\n"; } 
}; 
  
int main() 

     A a; 
     //return 0; 
     exit(0); 

如果用exit,那么main函数中的对象a将没有析构,而用return返回,a将被正常析构 
当没有exit(0)时,return 0时,系统会输出并清理缓冲区并关闭标准输入cin、标准输出cout、标准错误cerr、标准日志clog。

当有exit(0)时,c函数会输出并清理stdin, stdout,现在stdout已经被关闭了,在执行return 0时,cout的缓冲区的数据已经没有写入的目标了,所以无输出。

这只能说明cout和stdout, cin 和stdin用的是不同的缓冲区。
为什么用return 0 的时候对象b能自动调用析构函数,完全是编译器干的。
在c main函数中exit和return是相同的;而在c++中,编译器会将类析构函数的汇编代码插入到return前面,但对exit不作任何变动。
    C++ 中要尽量避免使用exit。

在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`或刷新缓冲区)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值