C语言异常处理之 setjmp()和longjmp()
2023-09-27 14:28:33 时间
异常处理之除0情况
相信大家处理除0时,都会通过函数,然后判断除数是否为0,代码如下所示:
double divide(doublea,double b)
{
const double delta = 0.00000000001; //由于浮点数不精确,所以需要定义个很小的数
if(!((-delta<b)&&(b<delta)))
{
return a/b ;
}
else
{
return 0;
}
}
其实这个函数还有瑕疵,当我们调用divide(0,1)时,返回值也是0,在程序运行时,根本无法判断返回值0是不是除法为0的原因.
其实可以通过setjmp()和longjmp()配合使用
描述
- 和goto很相似, 但是可以从一个函数到另外一个函数的跳转,常常用在异常处理上面.
- 这两个函数需要正确使用,否则会破坏程序顺序执行方式
- 头文件 #include <setjmp.h>
setjmp()和longjmp()
int setjmp(jmp_buf env);
将当前上下文保存在jmp_buf结构体中(入栈),并返回0
void longjmp(jmp_buf env,int val);
从env变量jmp_buf结构体中恢复setjmp()保存的上下文(出栈,并跳转)
由于跳转,所以会从setjmp函数调用点返回,返回值为val
跳转机制 (以 mian()函数 和 divide()函数 为例):
mian()函数 调用了 setjmp(env) ,将上下文(入栈)保存在env中,并返回0.
接着调用 divide()函数 进行除法操作.
进入 setjmp()函数 后,由于发现除法为0,所以使用 longjmp(env,1)函数 ,恢复 setjmp() 保存的上下文,也就是直接返回到了 main()函数 处理 setjmp(env) 的时候,并返回异常值1
代码实现:
#include <stdio.h> #include <setjmp.h>
jmp_buf env;
double divide(double a,double b) { const double delta = 0.00000000001; //由于浮点数不精确,所以需要定义个很小的数 if(!((-delta<b)&&(b<delta))) { return a/b ; } else { longjmp(env,1); //直接跳转到23行,ret=setjmp(env)代码处,并返回异常值(1) return 0; } } int main( ) { int ret; ret=setjmp(env); //手动调用 setjmp(),将返回正常值(0), if(!ret) //正常操作 { printf("5/0=%lf\n",divide(5,0)); } else if(ret==1) //异常操作 { printf("ERR\n"); } return 0; }
运行打印:
ERR
缺陷在于:
- 若需要两个函数之间跳转,必然要使用全局变量jmp_buf env
- 跳转使得代码可读性降低
相关文章
- C语言-5月10日 给一个不多于5位的正整数,要求:求出他是几位数,按照顺序输出各位数字,按照逆序输出各位数字。
- 【ARM-Linux开发】C语言getcwd()函数:取得当前的工作目录
- C语言中可变形参简单实例
- C语言open()函数:打开文件函数(转)
- C语言:随机生成数+希尔排序
- C语言:猴子上山问题递推算法实现
- C语言 - .c和.h文件的困惑
- C语言学习第一天
- 2022-09-17青少年软件编程(C语言)等级考试试卷(二级)解析
- 2021-09 青少年软件编程(C语言)等级考试试卷(五级)解析
- UVA-537--Artificial Intelligence?(C语言)
- linux下开发C语言需要安装的manpages手册
- C语言结构体初始化的四种方法
- 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(九)第一个程序背后的C语言知识
- 关于C语言遍历中英文字符串时的输出问题
- 李洪强漫谈iOS开发[C语言-014]-变量
- 深入浅出剖析C语言函数指针与回调函数(三)
- 【C语言基础】那些必会的编程练习题-第二部分