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