异常处理之除0情况

相信大家处理除0时,都会通过函数,然后判断除数是否为0,代码如下所示:

double divide(doublea,double b)
{
const double delta = 0.00000000001; //由于浮点数不精确,所以需要定义个很小的数 if(!((-delta<b)&&(b<delta)))
{
return a/b ;
}
else
{
return ;
}
}

其实这个函数还有瑕疵,当我们调用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语言异常处理之 setjmp()和longjmp()的更多相关文章

  1. C语言中setjmp与longjmp学习笔记

    C语言中setjmp与longjmp学习笔记 一.基础介绍 头文件:#include<setjmp.h> 原型:  int setjmp(jmp_buf envbuf) ,然而longjm ...

  2. 【转】浅析C语言的非局部跳转:setjmp和longjmp

    转自 http://www.cnblogs.com/lienhua34/archive/2012/04/22/2464859.html C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转 ...

  3. C语言再学习之 setjmp与longjmp

    前不久在阅读Quake3源代码的时候,看到一个陌生的函数:setjmp,一番google和查询后,觉得有必要针对setjmp和longjmp这对函数写一篇blog,总结一下. setjmp和longj ...

  4. C 语言中 setjmp 和 longjmp

    在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...

  5. 非本地跳转之setjmp与longjmp

    非本地跳转(unlocal jump)是与本地跳转相对应的一个概念. 本地跳转主要指的是类似于goto语句的一系列应用,当设置了标志之后,可以跳到所在函数内部的标号上.然而,本地跳转不能将控制权转移到 ...

  6. 第63课 C语言异常处理

    1. 异常的概念 (1)程序在运行过程中可能产生异常 (2)异常(Exception)与Bug的区别 ①异常是程序运行时可预料的执行分支 ②Bug是程序是的错误,是不被预期的运行方式 2. 异常和Bu ...

  7. setjmp()、longjmp() Linux Exception Handling/Error Handling、no-local goto

    目录 . 应用场景 . Use Case Code Analysis . 和setjmp.longjmp有关的glibc and eglibc 2.5, 2.7, 2.13 - Buffer Over ...

  8. c语言异常处理机制

    异常处理机制:setjmp()函数与longjmp()函数 C标准库提供两个特殊的函数:setjmp() 及 longjmp(),这两个函数是结构化异常的基础,正是利用这两个函数的特性来实现异常. 所 ...

  9. setjmp和longjmp

    此文是学习 C专家编程 中的笔记. setjmp和longjmp是C语言所独有的,它们部分弥补了C语言有限的转移能力. 函数说明(来自wiki百科): int setjmp(jmp_buf env) ...

随机推荐

  1. Linux系统安装 OpenSSL两种方法

    OpenSSL是一个开源的ssl技术,由于安装pytbull,需要安装openssl,并下载对应的版本下载地址:https://www.openssl.org/source/ 方法一,编译安装Open ...

  2. Firewalld的结构

    原文地址:http://www.excelib.com/article/287/show firewalld简介 Centos7中默认将原来的防火墙iptables升级为了firewalld,fire ...

  3. Redis-04.备份与恢复

    RDB(Redis DataBase) 在指定的时间间隔内将内存中的数据集快照写入磁盘,可以理解为Snapshot快照,它恢复时是将快照文件直接读到内存里. Redis会单独创建(fork)一个子进程 ...

  4. MySQL Schema与数据类型的优化

    选择优化的数据类型: 1. 更小的通常更好: 一般情况下,应该尽量使用可以正确存储数据的最小数据类型.更小的数据类型通常更快,因为他们占用更少的磁盘,内存和cpu缓存,并且处理时需要的cpu周期也更少 ...

  5. 知乎十万级容器规模的Java分布式镜像仓库实践

    作者:知乎令孤无忌 前言 知乎在 2016 年已经完成了全量业务的容器化,并在自研容器平台上以原生镜像的方式部署和运行,并在后续陆续实施了 CI.Cron.Kafka.HAProxy.HBase.Tw ...

  6. wordpress背景添加跟随鼠标动态线条特效

    今天看到别人的博客,在鼠标移动背景时会出现线条动态特效 感觉挺有意思的,还有另一种,在背景点击时会跳出字符特意去找了方法,以为需要添加代码的,结果只要安装个插件就可以了,所以说wordpress就是方 ...

  7. JavaScript 高性能数组去重

    中午和同事吃饭,席间讨论到数组去重这一问题 我立刻就分享了我常用的一个去重方法,随即被老大指出这个方法效率不高 回家后我自己测试了一下,发现那个方法确实很慢 于是就有了这一次的高性能数组去重研究 一. ...

  8. 初识vw和vh

     最近在项目里突然看到了一行css代码,height:100vh; 一时间有点蒙蔽 因为之前有听过这个css3新增单位,但没有去了解过. 那这个单位又跟px,rem,em,%有什么不同呢? 简述:   ...

  9. Metasploit Framework(2)Exploit模块、Payload使用

    文章的格式也许不是很好看,也没有什么合理的顺序 完全是想到什么写一些什么,但各个方面都涵盖到了 能耐下心看的朋友欢迎一起学习,大牛和杠精们请绕道 Exploit模块分为主动和被动(Active.Pas ...

  10. 一句话的事儿,Head first 设计模式

    head first 设计模式,是比较有趣的一本设计模式的书. 在学校里看书和在工作时看书,意义是不一样的.在学校时是为读书而读书,我们可以从0到1,我们有的是时间.但是工作后就不一样. 我觉得这时的 ...