一、概述

  • 1、exit()函数和_exit()函数都是用来 终止进程 的。
  • 2、return是C语言关键字,主要用于子函数的返回,标识这个子函数的结束。

二、函数说明

  当程序执行到 exit() 函数或者 _exit() 函数时候,进程无条件停止剩下的所有操作,清除各种数据结构,并终止本进程的运行

  但是,这两函数还是有区别的,函数的调用入下图2.1所示。

图2.1 exit()和_exit()函数流程图

  return 表示的是把程序流程从被调函数转向主调函数并把表达式的值带回主调函数,实现函数值的返回,返回时可附带一个返回值,由return后面的参数指定。

  综上所述:

  return:函数结束,是函数级别的结束,而 exit()_eixt() 是系统级别的结束。
    但是需要注意的是,在main函数中执行return语句,则整个进程结束。

  从图2.1中可以看出 _exit() 函数的作用是直接使进程停止运行,清除其使用的内存空间,并清除其在内核中的各种数据结构;而 exit() 函数则在这些基上做了一些包装,在执行退出之前加了若于道工序。

  exit() 函数与 _exit() 函数最大的区别就在于 exit() 函数在终止当前进程之前要检查该进程打开了哪些文件,并把文件缓冲区中的内容写回文件,就是图中的“清理IO缓冲”的表述。

  由于在Linux的标准函数库中,有一种被称为“缓冲IO(buffered I/O)”操作,其特征就是对应每一个打开的文件,在内存中都有一片缓冲区。

  每次读文件时,会连续读出若干条记录,这样在下次读文件时就可以直接从内存的缓冲区中读取;同样,每次写文件的时候,也仅仅是写入内存中的缓冲区,等满足了一定的条件(如达到一定数量或遇到特定字符等),再将缓冲区中的内容一次性写入文件。

  这种技术大大增加了文件读写的速度,但也为编程带来了一些麻烦,比如有些数据,认为已经被写入文件中,实际上因为没有满足特定的条件,它们还只是被保存在缓冲区内,这时用_exit()函数直接将进程关闭掉,缓冲区中的数据就会丢失。因此,若想保证数据的完整性,最好使用exit()函数。

  如果 main() 在一个递归程序中,exit() 仍然会终止程序,但是 return 将控制权移交给递归的前一级,直到最初的那一级,此时 return 才会终止程序。returnexit() 的另一个区别在于,即使在除了 main() 之外的函数中调用 exit(),它也将终止整个进程。

三、exit()函数和exit()函数的语法

  1 exit()函数和_exit()函数的原型以及头文件

#include <stdlib.h>

void exit(int status);
#include <unistd.h>

void _exit(int status);

  2 exit()函数和_exit()函数的参数

  status 是一个整型参数,可以利用这个参数传递 进程结束时的状态,一般来说,exit(0) 表示程序正常退出,exit(1) 或者 exit(-1) 表示程序异常退出。

  标准C里有EXIT_SUCCESSEXIT_FAILURE 两个宏,定义于头文件 stdlib.h 中:

/* We define these the same for all machines.
   Changes from this to the outside world should be done in `_exit'.  */
#define EXIT_FAILURE    1       /* Failing exit status.  */
#define EXIT_SUCCESS    0       /* Successful exit status.  */

  推荐在实际编程时候用 exit(EXIT_SUCCESS) 来表示正常退出, exit(EXIT_FAILURE) 来表示异常退出,更加方便代码阅读与理解。

  在实际编程中,可以用 wait() 系统调用来接收 子进程 的返回值,从而根据不同的返回值进行不同的处理。

  2 exit()函数和_exit()函数的用法

  exit() 函数和 _exit() 函数是两个简单的正经函数,return 也是正经的关键字。用下面的三个示例程序已经足够说明了。

  1) exit() 函数用法

#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char *argv[])
{
    /* 标准输出流stdout是行缓冲,遇到“\n”换行符时才实际写入终端。 */
    printf("Using exit...\n");
    /* 下一个输出不输出换行符 */
    printf("This is the content in buffer.");

    exit(0); /* 调用exit函数测试 */

    printf("After the exit...\n");

    return 0;
}

  经过简单的编译与运行,可以看见运行效果如下图3.1所示。

图3.1 exit()函数运行效果图

  2) _exit() 函数的用法

#include <stdio.h>
#include <unistd.h>

int main(int argc, const char *argv[])
{
    /* 标准输出流stdout是行缓冲,遇到“\n”换行符时才实际写入终端。 */
    printf("Using _exit...\n"); /* NOTE 于2024.09.11修正原先的问题 */
    /* 下一个输出不输出换行符 */
    printf("This is the content in buffer.");

    _exit(0); /* 调用_exit函数测试 */

    printf("After the _exit...\n");

    return 0;
}

  经过简单的编译与运行,可以看见运行效果如下图3.2所示(于2024.09.11同步更新图片)。

图3.2 _exit()函数运行效果图

  3) return 的用法

#include <stdio.h>
#include <stdlib.h> // for EXIT_SUCCESS

int return_test(int num)
{
    if (num == 0)
    {
        return 0; /* 如果num为0,说明递归要结束了 */
    }
    else
    {
        /* 返回自身与下一个数的加和 */
        return num + return_test(num - 1);
    }
}

int main(int argc, const char *argv[])
{
    /* 定义一个测试变量并初始值为100 */
    int num = 100;

    printf("Testing return...\n");

    /* 调用测试函数,实现0-100的加和的操作 */
    int cnt = return_test(num);

    /* 测试执行位置并输出结果 */
    printf("cnt = %d\n", cnt);

    /* 在程序中途进行return */
    return EXIT_SUCCESS;

    printf("After the return...\n");

    return 0;
}

  经过简单的编译与运行,可以看见运行效果如下图3.3所示。

图3.3 return 运行效果图

  
  好啦,废话不多说,总结写作不易,如果你喜欢这篇文章或者对你有用,请动动你发财的小手手帮忙点个赞,当然 关注一波 那就更好了,好啦,就到这儿了,么么哒(*  ̄3)(ε ̄ *)。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐