setjmp和longjmp的使用(个人修改其中一部分)

来源:互联网 发布:mac切换繁体中文 编辑:程序博客网 时间:2024/04/29 10:35

转载:http://blog.csdn.net/legone2008/article/details/2323710,感谢legone2008博主。


setjmplogjmp包含在头文件/usr/include/setjmp.h,使用前应在程序头部加入#include <setjmp.h>

setjmplongjmp结合使用时,它们必须有严格的先后执行顺序,也即先调用setjmp函数,之后再调用longjmp函数,以恢复到先前被保存的程序执行点。否则,如果在setjmp调用之前,执行longjmp函数,将导致程序的执行流变的不可预测,很容易导致程序崩溃而退出。

setjmplongjmp的作用同goto语句类似,它能实现本地的跳转.

 

.setjmplogjmp的使用场合:

1.人们对于goto语句的忌讳,很多的专业书籍以及专业人士号召限制goto语句的使用,此时,setjmplongjmpgoto语句有了很好的替代作用.
2.goto
语句有一个局限性,它只能在函数内部跳转.setjmplongjmp可以在整个程序全局中跳转,实现"长跳转",弥补了goto功能的局限.
3.
使用setjmplongjmp可以捕捉程序中的异常,并采取异常处理机制.

.使用setjmp设置跳转点,longjmp回到原设置点
setjmplongjmp必须结合起来使用;
函数原型:int setjmp(jmp_buf env);
setjmp(env):
设置jumper,jumper是一个jmp_buf类型变量.setjmp.h文件中有jmp_buf的定义,可见它是一个结构体数组.
/* Calling environment, plus possngibly a saved signal mask.  */

typedef struct __jmp_buf_tag    /* C++ doesn't like tagless structs.  */

{

   /* NOTE: The machine-dependent definitions of `__sigsetjmp'

    assume that a `jmp_buf' begins with a `__jmp_buf' and that

    `__mask_was_saved' follows it.  Do not move these members

    or add others before it.  */

     __jmp_buf __jmpbuf;     /* Calling environment.  */

    int __mask_was_saved;   /* Saved the signal mask?  */

    __sigset_t __saved_mask;    /* Saved signal mask.  */

} jmp_buf[1];

 

调用该函数对env初始化,初始化后返回一个int值,第一次调用,这个int值为0;


函数原型:void longjmp(jmp_buf env, int val);

第一个参数:setjmp(env)设置的jumper点.

第二个参数:给setjmp(env)重新赋值,为val值.

:

#include <stdio.h>#include <setjmp.h>void subroutine(void);void subroutine_2(void); jmp_buf jumper; main(){    int value;    int i = 0;    value = setjmp(jumper);   /* 设置jump点,初始化jumper,返回值0赋给value, */    i++;    printf("执行第[%d]次:value = [%d]: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>/n",i,value);    if(value == 0)    {        printf("[1]About to call subroutine...../n");        subroutine();  /* 调转到subroutine()函数 */        printf("Never go this..../n");    }    else if(value == 1)    {        printf("[2]About to call subroutine...../n");        subroutine_2();  /* 调转到subroutine_2()函数 */        printf("Never go this..../n");    }    else    {        printf("[3]Never go this..../n");    }    return 0;}void subroutine(void){      /* 调转到jumper初始化的地方,即setjmp(jumper)处,并将1赋给set(jumper) */    longjmp(jumper,1);    return;}void subroutine_2(void){      /* 调转到jumper初始化的地方,即setjmp(jumper)处,并将3赋给set(jumper) */    longjmp(jumper,3);    return;}

程序的运行结果如下图所示:



.使用setjmp,longjmp处理异常.

#include <stdio.h>#include <setjmp.h>jmp_buf jumper;void exception();int  deal_exception();main(){     int value;     int i = 0;     value = setjmp(jumper);   /* 设置jump点,初始化jumper,返回值0赋给value, */     if ( 0 == value ) {         exception();     }     else {         switch ( value )         {            case 1:                printf( "解决异常情况[%d]/n",value );                break;            case 2:                printf( "解决异常情况[%d]/n",value );                break;            case 3:                printf( "解决异常情况[%d]/n",value );                break;           default:                printf( "异常情况[%d]未知/n",value );                break;        }    }}void exception(){    int _err_no;    if ( _err_no = 3 ) {        printf("出现异常情况[%d]/n",_err_no);        longjmp(jumper,_err_no);    }    return;}
程序执行结果:



以上为本人学习setjmplongjmp后所做的总结,做为新手,文中例子并不能最好的表现使用setjmplongjmp后的优势,但也能说明这两个函数如何使用.文中如有不当之处,也欢迎批评指正.

0 0
原创粉丝点击