理解C语言中的花式退出

代码test_Exit.c 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 
 5 //简单输出fun1被调用的提示信息
 6 void fun1(void){
 7     printf("[%s] is called...\n", __FUNCTION__);
 8 }
 9 
10 //简单输出fun2被调用的提示信息
11 void fun2(void){
12     printf("[%s] is called...\n", __FUNCTION__);
13 }
14 
15 int main(int argc, char **argv)
16 {
17     //表示在要在函数退出前进行函数的调用
18     atexit(fun1);
19     //调用顺序为LIFO方式,也就是说先执行第20行,再执行第18行
20     atexit(fun2);
21 
22     //printf()函数中没有\n,也就是只输出,不刷新
23     printf("abcdef");
24 
25     //_exit()是一种退出,这种退出不处理退出函数,也不刷新IO                    
26     _exit(0);
27 }

程序很简单,不多说明

结果是:

 

对,你没有看错,就是什么也没有,什么也没有了。虽然调用了printf()函数输出了字符串,但是函数退出前没有刷新IO,所有字符串并没有被输出。

接下来testN_exit.c,将23行改为:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 
 5 //简单输出fun1被调用的提示信息
 6 void fun1(void){
 7     printf("[%s] is called...\n", __FUNCTION__);
 8 }
 9 
10 //简单输出fun2被调用的提示信息
11 void fun2(void){
12     printf("[%s] is called...\n", __FUNCTION__);
13 }
14 
15 int main(int argc, char **argv)
16 {
17     //表示在要在函数退出前进行函数的调用
18     atexit(fun1);
19     //调用顺序为LIFO方式,也就是说先执行第20行,再执行第18行
20     atexit(fun2);
21 
22     //printf()函数中添加\n,也就是既输出,又刷新                               
23     printf("abcdef\n");
24 
25     //_exit()是一种退出,这种退出不处理退出函数,也不刷新IO
26     _exit(0);
27 }

结果是:

abcdef

表明_exit(0)只负责退出,而刷新IO只能靠\n解决了

接下来:testExit.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 
 5 //简单输出fun1被调用的提示信息
 6 void fun1(void){
 7     printf("[%s] is called...\n", __FUNCTION__);
 8 }
 9 
10 //简单输出fun2被调用的提示信息
11 void fun2(void){
12     printf("[%s] is called...\n", __FUNCTION__);
13 }
14 
15 int main(int argc, char **argv)
16 {
17     //表示在要在函数退出前进行函数的调用
18     atexit(fun1);
19     //调用顺序为LIFO方式,也就是说先执行第20行,再执行第18行
20     atexit(fun2);
21 
22     //printf()函数中没有\n,也就是只输出,不刷新                               
23     printf("abcdef");
24 
25     //_exit()是一种退出,这种退出不处理退出函数,也不刷新IO
26     exit(0);
27 }

相较test_Exit.c只是把_exit()换成了exit(),代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 
 5 //简单输出fun1被调用的提示信息
 6 void fun1(void){
 7     printf("[%s] is called...\n", __FUNCTION__);
 8 }
 9 
10 //简单输出fun2被调用的提示信息
11 void fun2(void){
12     printf("[%s] is called...\n", __FUNCTION__);
13 }
14 
15 int main(int argc, char **argv)
16 {
17     //表示在要在函数退出前进行函数的调用
18     atexit(fun1);
19     //调用顺序为LIFO方式,也就是说先执行第20行,再执行第18行
20     atexit(fun2);
21 
22     //printf()函数中没有\n,也就是只输出,不刷新                               
23     printf("abcdef");
24 
25     //exit()这种退出,不但处理退出函数,而且刷新IO
26     exit(0);
27 }

结果:

abcdef[fun2] is called...
[fun1] is called...

就会发现,exit()函数不但完成了刷新IO的任务,同时也完成函数退出前的所有任务,调用atexit()函数是按照栈的方式调用的,但是还是有点缺陷的。

下面testNExit.c为:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 
 5 //简单输出fun1被调用的提示信息
 6 void fun1(void){
 7     printf("[%s] is called...\n", __FUNCTION__);
 8 }
 9 
10 //简单输出fun2被调用的提示信息
11 void fun2(void){
12     printf("[%s] is called...\n", __FUNCTION__);
13 }
14 
15 int main(int argc, char **argv)
16 {
17     //表示在要在函数退出前进行函数的调用
18     atexit(fun1);
19     //调用顺序为LIFO方式,也就是说先执行第20行,再执行第18行
20     atexit(fun2);
21 
22     //printf()函数中有\n,也就是不但输出,而且刷新                             
23     printf("abcdef\n");
24 
25     //exit()是这种退出,不但处理退出函数,同时刷新IO
26     exit(0);
27 }

结果为:

abcdef
[fun2] is called...
[fun1] is called...

很明显可以看出,exit()完成了IO的刷新,\n完成了换行,终于实现了我们需要的结果,其实这里的exit(0)完全等价于我们的return 0语句,它也只不过是个宏定义而已。

posted @ 2021-08-27 17:21  叕叒双又  阅读(320)  评论(0编辑  收藏  举报