C语言异常处理之 setjmp()和longjmp()

异常处理之除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
  • 跳转使得代码可读性降低

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏达摩兵的技术空间

es6入门

es6作为最新的js语言版本,有很多特性是不得不晓的。下面将语法中常用的分析出来,对应到基本对象类型的会在对象里描述。

942
来自专栏coolblog.xyz技术专栏

Dubbo 源码分析 - SPI 机制

SPI 全称为 Service Provider Interface,是 Java 提供的一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,...

741
来自专栏海天一树

小朋友学Python(19):异常

一、什么是异常 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。 一般情况下,在Python无法正常处理程序时就会发生一个异常。 异常是P...

3389
来自专栏数据结构与算法

3186 队列练习 2

3186 队列练习 2 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description (此题...

2625
来自专栏Java技术栈

IntegerCache的妙用和陷阱!

考虑下面的小程序,你认为会输出为什么结果? public class Test { public static void main(String[...

3555
来自专栏程序员互动联盟

【编程基础第十一讲】代码如何写才最漂亮第一篇

存在问题: 好多小伙伴对编码的格式作用模糊,以为只要完成功能就行,其实这种观点是错误的,一定要重视代码规范,不然你哭的地都找不到。 如何实施: 良好的代码开发习...

2777
来自专栏爱撒谎的男孩

Spring依赖注入

4407
来自专栏情情说

深入浅出MyBatis:反射和动态代理

前三篇详细总结了Mybatis的基本特性、常用配置、映射器,相对于Hibernate,映射器的配置相对复杂,但有很好的灵活性和扩展性,可以应对各种业务场景。熟练...

4477
来自专栏逍遥剑客的游戏开发

PL/0语言编译程序分析

3085
来自专栏java一日一条

一个Java对象到底占用多大内存

大家可以用这个代码边看边验证,注意的是,运行这个程序需要通过javaagent注入Instrumentation,具体可以看原博客。我今天主要是总结下手动计算J...

681

扫码关注云+社区

领取腾讯云代金券