当前位置: 首页 > news >正文

C语言入门系列:特殊的main函数和exit函数

文章目录

  • 一,main函数
  • 二,exit函数
    • 1,exit函数
    • 2,atexit()函数
      • 2.1 atexit函数的简介
      • 2.2 atexit注册的函数一定会被调用吗
        • 2.2.1 正常退出测试
        • 2.2.2 异常退出测试

一,main函数

在这里插入图片描述

一个C程序至少包含一个函数,这个函数就是main()函数,它是程序的入口点。

main()负责调用其他函数,完成程序的主要任务。

#include <stdio.h>int main() {printf("Hello, World!\n");return 0; // 程序正常结束
}

main()函数的声明和普通函数并无区别,也包含函数头和函数体,函数头包含返回值类型、函数名称、参数列表,函数体中包含return语句。

正常情况下,如果main()里面省略return语句,编译器不会警告或者报错,相当于编译器会自动加上return语句,可以认为main()的默认返回值为0。所以,也可以写成下面这样。

#include <stdio.h>int main() {printf("Hello, World!\n");// 省略return 0; 程序正常结束
}

二,exit函数

1,exit函数

exit()

exit()函数的作用是终止整个程序,原型定义在头文件stdlib.h里面,引入头文件后,我们可以直接在其他函数中使用。

exit()可以起到return的作用,向函数外部返回一个值,返回值是传递给exit()的参数。

exit()的参数通常是两个常量:

  • EXIT_SUCCESS(相当于 0)表示程序运行成功
  • EXIT_FAILURE(相当于 1)表示程序异常中止。

这两个常量的定义包含在stdlib.h里面。

// 程序运行成功
// 等同于 exit(0);
exit(EXIT_SUCCESS);// 程序异常中止
// 等同于 exit(1);
exit(EXIT_FAILURE);

在main()函数里面,exit()等同于使用return语句。

#include <stdio.h>int main() {printf("Hello, World!\n");// 等同于return 0;exit(EXIT_SUCCESS);
}

其他函数使用exit(),就是终止整个程序的运行,没有其他作用。

#include <stdio.h>
#include <stdlib.h>int plus1(int num){exit(0);
}int main()
{printf("Hello World");int num = plus1(0);printf("num=%d",num);
}

如上代码,main函数中调用plus1()plus1中调用了exit函数,执行exit函数后,整个程序就结束,不会再执行main函数的最后一行代码。

也即是说,我们在普通函数中调用exit函数时传递参数,是没有什么意义的。

2,atexit()函数

2.1 atexit函数的简介

C 语言还有一个atexit()函数,用来告知编译器在exit()执行之前,执行一个指定的函数,这个程序可以称之为终止处理程序,通常用来执行程序结束前的资源回收工作,比如释放内存、释放数据库连接等等,或者程序异常退出前打印异常信息。

该函数的原型定义在头文件stdlib.h。

int atexit(void (*func)(void));

注意,atexit()的参数是一个函数指针,且这个指针指向的函数必须满足如下两个条件:

  • 不接受任何参数。
  • 不能有返回值。
void releaseSomething(void) {printf("releaseMemory\n");printf("releaseDBLink\n");
}
atexit(releaseSomething);
exit(EXIT_SUCCESS);

上面示例中,exit()执行时,会先调用atexit()函数注册的releaseSomething()函数,之后终止程序。

可以通过atexit注册多个终止处理程序,同一个函数若注册多次,那它也会被调用多次。

POSIX.1-2001 规定,至少可以注册 32 个终止处理程序,若想查看实际可以注册多少个终止处理程序,可以通过调用 sysconf()函数获得。

2.2 atexit注册的函数一定会被调用吗

如果程序异常退出,atexit注册的函数不一定会被调用。

以下5种程序终止方式会调用atexit注册的函数。

  • ① 从main返回

  • ② 调用exit函数

  • ③调用 _exit 或 _Exit

  • ④最后一个线程从其启动例程返回

  • ⑤最后一个线程调用pthread_exit

下面三种异常终止的情况不会调用atexit注册的函数:

  • ① 调用 abort
  • ② 接到一个信号并终止
  • ③ 最后一个线程对取消请求做出响应
2.2.1 正常退出测试

测试代码:

#include <stdio.h>
#include <stdlib.h>void fn1(void);
int main(void) {printf("main begain!\n");atexit(fn1);printf("main exit!\n");return 0;
}void fn1() {printf("fn1 exit!\n");
}

结果显示,程序退出前执行了atexit注册的函数。
在这里插入图片描述

2.2.2 异常退出测试

测试代码:

#include <stdio.h>
#include <stdlib.h>void fn1(void);
int main(void) {printf("main begain!\n");atexit(fn1);// 发出中断信号abort();printf("main exit!\n");return 0;
}void fn1() {printf("fn1 exit!\n");
}

结果显示,程序终止前没有执行atexit注册的函数。

在这里插入图片描述

相关文章:

  • pandas plot函数:数据可视化的快捷通道
  • 【java】写一个发送邮箱的样例
  • 点击旋转箭头样式
  • Java宝藏实验资源库(2)字节流
  • ios CCLanguage.m
  • VMware ESXi 8.0U2c macOS Unlocker OEM BIOS Huawei (华为) FusionServer 定制版
  • 3D开发工具HOOPS为BIM应用提供支持:复杂大模型实现Web端轻量化!
  • 【Android面试八股文】Kotlin内置标准函数also的原理是什么?
  • Java学习 - 网络静态路由与动态路由 讲解
  • Ubuntu 24.04安装zabbix7.0.0图形中文乱码
  • MinIO 网络与覆盖网络
  • 【0-1系列】从0-1快速了解搜索引擎Scope以及如何快速安装使用(下)
  • rclone 上传资料到 onedrive 遇到限速问题解决
  • JS中正则表达式的语法与使用案例
  • 字节豆包全新图像Tokenizer:生成图像最低只需32个token,最高提速410倍
  • 收藏网友的 源程序下载网
  • [iOS]Core Data浅析一 -- 启用Core Data
  • canvas 绘制双线技巧
  • CentOS 7 防火墙操作
  • CSS3 变换
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • express + mock 让前后台并行开发
  • GitUp, 你不可错过的秀外慧中的git工具
  • Java超时控制的实现
  • JDK 6和JDK 7中的substring()方法
  • js如何打印object对象
  • linux学习笔记
  • magento2项目上线注意事项
  • maya建模与骨骼动画快速实现人工鱼
  • Python利用正则抓取网页内容保存到本地
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • 安卓应用性能调试和优化经验分享
  • 笨办法学C 练习34:动态数组
  • 初识 beanstalkd
  • 从PHP迁移至Golang - 基础篇
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 前端工程化(Gulp、Webpack)-webpack
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 什么是Javascript函数节流?
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 阿里云ACE认证学习知识点梳理
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • $.ajax,axios,fetch三种ajax请求的区别
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (二)JAVA使用POI操作excel
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (转)memcache、redis缓存
  • (转载)深入super,看Python如何解决钻石继承难题
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .Net MVC4 上传大文件,并保存表单
  • .Net mvc总结