setjmp與longjmp包含在頭文件/usr/include/setjmp.h中,使用前應在程序頭部加入#include <setjmp.h>。 setjmp與longjmp結合使用時,它們必須有嚴格的先后執(zhí)行順序,也即先調(diào)用setjmp函數(shù),之后再調(diào)用longjmp函數(shù),以恢復到先前被保存的“程序執(zhí)行點”。否則,如果在setjmp調(diào)用之前,執(zhí)行l(wèi)ongjmp函數(shù),將導致程序的執(zhí)行流變的不可預測,很容易導致程序崩潰而退出。 setjmp與longjmp的作用同goto語句類似,它能實現(xiàn)本地的跳轉(zhuǎn).
一.setjmp與logjmp的使用場合: 1.人們對于goto語句的忌諱,很多的專業(yè)書籍以及專業(yè)人士號召限制goto語句的使用,此時,setjmp與longjmp對goto語句有了很好的替代作用. 2.goto語句有一個局限性,它只能在函數(shù)內(nèi)部跳轉(zhuǎn).而setjmp與longjmp可以在整個程序全局中跳轉(zhuǎn),實現(xiàn)"長跳轉(zhuǎn)",彌補了goto功能的局限. 3.使用setjmp和longjmp可以捕捉程序中的異常,并采取異常處理機制. 二.使用setjmp設置跳轉(zhuǎn)點,longjmp回到原設置點 setjmp與longjmp必須結合起來使用; 函數(shù)原型:int setjmp(jmp_buf env); setjmp(env):設置jumper點,jumper是一個jmp_buf類型變量.在setjmp.h文件中有jmp_buf的定義,可見它是一個結構體數(shù)組. /* 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];
調(diào)用該函數(shù)對env初始化,初始化后返回一個int值,第一次調(diào)用,這個int值為0; 函數(shù)原型:void longjmp(jmp_buf env, int val); 第一個參數(shù):setjmp(env)設置的jumper點. 第二個參數(shù):給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("執(zhí)行第[%d]次:value = [%d]: >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n",i,value ); if(value == 0) { printf("[1]About to call subroutine.....\n"); subroutine(); /* 調(diào)轉(zhuǎn)到subroutine()函數(shù) */ printf("Never go this....\n"); } else if(value == 1) { printf("[2]About to call subroutine.....\n"); subroutine_2(); /* 調(diào)轉(zhuǎn)到subroutine_2()函數(shù) */ printf("Never go this....\n"); } else { printf("[3]Never go this....\n"); } return 0; } void subroutine(void) { /* 調(diào)轉(zhuǎn)到jumper初始化的地方,即setjmp(jumper)處,并將1賦給set(jumper) */ longjmp(jumper,1); return; } void subroutine_2(void) { /* 調(diào)轉(zhuǎn)到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("出現(xiàn)異常情況[%d]\n",_err_no); longjmp(jumper,_err_no); } return; } |
|