setjmp与logjmp包含在头文件/usr/include/setjmp.h中,使用前应在程序头部加入#include <setjmp.h>。
setjmp与longjmp结合使用时,它们必须有严格的先后执行顺序,也即先调用setjmp函数,之后再调用longjmp函数,以恢复到先前被保存的“程序执行点”。否则,如果在setjmp调用之前,执行longjmp函数,将导致程序的执行流变的不可预测,很容易导致程序崩溃而退出。
setjmp与longjmp的作用同goto语句类似,它能实现本地的跳转.
一.setjmp与logjmp的使用场合:
1.人们对于goto语句的忌讳,很多的专业书籍以及专业人士号召限制goto语句的使用,此时,setjmp与longjmp对goto语句有了很好的替代作用.
2.goto语句有一个局限性,它只能在函数内部跳转.而setjmp与longjmp可以在整个程序全局中跳转,实现"长跳转",弥补了goto功能的局限.
3.使用setjmp和longjmp可以捕捉程序中的异常,并采取异常处理机制.
二.使用setjmp设置跳转点,longjmp回到原设置点
setjmp与longjmp必须结合起来使用;
函数原型: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;
}
以上为本人学习setjmp的longjmp后所做的总结,做为新手,文中例子并不能最好的表现使用setjmp和longjmp后的优势,但也能说明这两个函数如何使用.文中如有不当之处,也欢迎批评指正.