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

setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序员的预先设计的意图,去实现对程序中可能出现的异常进行集中处理。

先来看一下这两个函数的定义吧:

setjmp和longjmp的函数原型在setjmp.h中

函数原型:

int setjmp(jmp_buf envbuf);

setjmp函数用缓冲区envbuf保存系统堆栈的内容,以便后续的longjmp函数使用。setjmp函数初次启用时返回0值。

void longjmp(jmp_buf envbuf, int val);

longjmp函数中的参数envbuf是由setjmp函数所保存的堆栈环境,参数val设置setjmp函数的返回值。longjmp函数本身是没有返回值的,它执行后跳转到保存envbuf参数的setjmp函数调用,并由setjmp函数调用返回,此时setjmp函数的返回值就是val。

上面的说明有点拗口,通俗的解释是:先调用setjmp,用变量envbuf记录当前的位置,然后调用longjmp,返回envbuf所记录的位置,并使setjmp的返回值为val。当时用longjmp时,envbuf的内容被销毁了。其实这里的“位置”一词真正的含义是栈定指针。

接着让我们看一个小例子吧:

#include <stdio.h> 
#include <setjmp.h>

jmp_buf buf;

banana(){ 
    printf("in banana() \n"); 
    longjmp(buf,1);

printf("you'll never see this,because i longjmp'd");

}

main() 

    if(setjmp(buf)) 
        printf("back in main\n"); 
    else{ 
        printf("first time through\n"); 
        banana(); 
    }

}

(代码段引自《C专家编程》:p)

这段代码的打印结果是:

first time through

in banana()

back in main

仔细看一下应该更能体会这对函数的作用了吧。

setjmp/longjmp的最大用处是错误恢复,类似try ...catch...

他们的功能比goto强多了,goto只能在函数体内跳来跳去,而setjmp/longjmp可以在到过的所有位置间。

从java、.net世界来的兄弟们也许会很不屑于这对函数,也许会觉得这样的功能会使代码的可读性变差。不过请别忘了,这里是C的世界,每个世界有每个世界的哲学,OO只是方法学的一种,而不是全部。quake3是用C写的,据看过其代码的前辈说,其模块化非常好,所以这也是我看quake3代码的初衷。(哦,算了吧,写游戏不是随便说说的...)

C语言再学习之 setjmp与longjmp的更多相关文章

  1. 学习之"setjmp和longjmp函数"

    Linux学习之"setjmp和longjmp函数"   转贴,原文地址:http://www.cnblogs.com/lq0729/archive/2011/10/23/2222 ...

  2. C语言再学习part1-宏观认识C语言

    天下莫柔弱于水,而攻坚强者莫之能胜,以其无以易之也.弱之胜强,柔之胜刚,天下莫不知行,莫能行. —老子 我近来每天都在坚持读书,所以我一直沉浸于古人的智慧中无法自拔.所以如果我这篇博文被你有幸看到,那 ...

  3. C语言再学习之内存对齐

    昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵.一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧: #define _I ...

  4. C语言再学习part3—算法

    君子远庖厨,万物皆备于我.—孟子 这篇文章主要总结程序的主要要素,以及程序的构成是什么样子的.最后说说我学到的一种奇特的表示算法的方式—伪代码. 让我们开始吧! 一个程序应该包括以下两个主要要素: 1 ...

  5. C语言再学习part2-重新认识C语言词汇

    迷阳迷阳,无伤吾行.无行郗曲,无伤吾足.—庄子 C语言词汇: 标识符 在程序中的变量名.函数名.标号等等成为标识符.其中标识符相在C中只能是字母A~Z,a~z,数字0~9,下划线(_)组成的字符串,并 ...

  6. 01_c语言再学习_基础部分(1)

    目录: 1.编译基础 2.c语言关键字 3.c语言数据类型 4.二进制/8进制/16进制 5.计算机内存数值存储方式:sizeof/原码/反码/补码 6.c语言中的字符和字符串 7.c语言中的数组和字 ...

  7. 非本地跳转之setjmp与longjmp

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

  8. MQTT再学习 -- MQTT 客户端源码分析

    MQTT 源码分析,搜索了一下发现网络上讲的很少,多是逍遥子的那几篇. 参看:逍遥子_mosquitto源码分析系列 参看:MQTT libmosquitto源码分析 参看:Mosquitto学习笔记 ...

  9. FFmpeg再学习 -- SDL 环境搭建和视频显示

    继续看雷霄骅的 课程资料 - 基于FFmpeg+SDL的视频播放器的制作 一.SDL 简介 参看:WIKI -- Simple DirectMedia Layer 参看:最简单的视音频播放示例9:SD ...

随机推荐

  1. 【MVVM 原生】原生MVVM的使用

    一.前言       前些天需要完成一个任务,该任务属于公司的一些核心代码,为了避免不必要的麻烦,任务要求不能使用第三方的MVVM框架,必须用原生的. 平时习惯了Dev与MVVMLight,遇上原生的 ...

  2. Splitter Control for Dialog

    原文链接地址:https://www.codeproject.com/Articles/595602/Splitter-Control-for-Dialog Introduction Yes, tha ...

  3. 洛谷 P2258 子矩阵

    题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4.5列交叉位置的元素 ...

  4. NOIP2016愤怒的小鸟 题解报告 【状压DP】

    题目什么大家都清楚 题解 我们知道,三点确定一条抛物线,现在这条抛物线过原点,所以任意两只猪确定一条抛物线.通过运算的出对于两头猪(x1,y1),(x2,y2),他们所在抛物线a=(y1*x2-y2* ...

  5. 洛谷 P4169 [Violet]天使玩偶/SJY摆棋子 解题报告

    P4169 [Violet]天使玩偶/SJY摆棋子 题目描述 \(Ayu\)在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,\(Ayu\) 却忘了她把天使玩偶埋在了哪 ...

  6. 《JavaScript高级程序设计(第三版)》-3

    相等操作符 相等和不相等 在转换不同的数据类型时,相等和不想等操作符遵循下面基本规则: 如果有一个操作符数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1: 如果 ...

  7. Emgu.CV.CvInvoke”的类型初始值设定项引发异常

    http://zhidao.baidu.com/link?url=VHkw3qZxp7HumQX_r-4ljPiy-N4A7yNK1Xn5q6tjPb16WvBGy6RFKrmKEhtgJ2PACAk ...

  8. [POI2014] KUR-Couriers (主席树)

    [POI2014]KUR-Couriers 题目描述 Byteasar works for the BAJ company, which sells computer games. The BAJ c ...

  9. [JLOI2014] 松鼠的新家 (lca/树上差分)

    [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在 ...

  10. centos中设置swap交换空间的大小设置和swappiness的比例设置

    首先使用free -m命令查看内存使用情况和swap的大小 关闭swap: 设置swap的大小: bs指的是Block Size,就是每一块的大小.这里的例子是1M,意思就是count的数字,是以1M ...