Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6457258
  • 博文数量: 579
  • 博客积分: 1548
  • 博客等级: 上尉
  • 技术积分: 16635
  • 用 户 组: 普通用户
  • 注册时间: 2012-12-12 15:29
个人简介

http://www.csdn.net/ http://www.arm.com/zh/ https://www.kernel.org/ http://www.linuxpk.com/ http://www.51develop.net/ http://linux.chinaitlab.com/ http://www.embeddedlinux.org.cn http://bbs.pediy.com/

文章分类

全部博文(579)

文章存档

2018年(18)

2015年(91)

2014年(159)

2013年(231)

2012年(80)

分类: C/C++

2013-02-03 16:03:45

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
#include

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代码的初衷。 (哦,算了吧,写游戏不是随便说说的...)

注:

   我第一次看到setjmp是在quake3代码的Com_Init中,

/*
=================
Com_Init
=================
*/
void Com_Init( char *commandLine ) {
    char    *s;

    Com_Printf( "%s %s %s\n", Q3_VERSION, CPUSTRING, __DATE__ );

    if ( setjmp (abortframe) ) {
        Sys_Error ("Error during initialization");
    }

....

卡马克在这里也是当catch用的,其中的一句注释是这么写的:

jmp_buf abortframe;        // an ERR_DROP occured, exit the entire frame

阅读(2601) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~