setjmp和longjmp是C語言獨有的,只有將它們結合起來使用,才能達到程序控制流有效轉移的目的,按照程序員的預先設計的意圖,去實現對程序中可能出現的異常進行集中處理。程序員
setjmp和longjmp的函數原型在setjmp.h中函數
函數原型:設計
int setjmp(jmp_buf envbuf);setjmp函數用緩衝區envbuf保存系統堆棧的內容,以便後續的longjmp函數使用。setjmp函數初次啓用時返回0值。code
void longjmp(jmp_buf envbuf, int val);longjmp函數中的參數envbuf是由setjmp函數所保存的堆棧環境,參數val設置setjmp函數的返回值。longjmp函數自己是沒有返回值的,它執行後跳轉到保存envbuf參數的setjmp函數調用,並由setjmp函數調用返回,此時setjmp函數的返回值就是val。原型
jmp_buf 記錄了棧、指令位置等信息:it
1,若是有多個setjmp 使用同一個jmp_buf, 那麼longjmp會跳轉到最近的setjmp位置: class
#include "apue.h" #include <setjmp.h> static void f1(int, int, int, int); static void f2(void); static jmp_buf jmpbuffer; static int globval; int main(void) { int autoval; register int regival; volatile int volaval; static int statval; globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5; if (setjmp(jmpbuffer) != 0) { printf("in main,after longjmp:\n"); printf("globval = %d, autoval = %d, regival = %d," " volaval = %d, statval = %d\n", globval, autoval, regival, volaval, statval); exit(0); } /* * Change variables after setjmp, but before longjmp. */ globval = 95; autoval = 96; regival = 97; volaval = 98; statval = 99; f1(autoval, regival, volaval, statval); /* never returns */ exit(0); } static void f1(int i, int j, int k, int l) { printf("in f1():\n"); printf("globval = %d, autoval = %d, regival = %d," " volaval = %d, statval = %d\n", globval, i, j, k, l); if(setjmp(jmpbuffer) != 0){ printf("in f1, after longjmp!"); //longjmp(jmpbuffer,2); exit(0); } f2(); } static void f2(void) { printf("in f2"); longjmp(jmpbuffer, 1); }
2, 下面的使用方式會造成死循環:循環
if( setjmp(jmpbuffer) != 0 ){ printf("in f1, after longjmp!"); longjmp(jmpbuffer,2); exit(0); }
3, 若是想實現多個不一樣的跳轉,可使用多個jmp_buf :程序
#include "apue.h" #include <setjmp.h> static void f1(int, int, int, int); static void f2(void); static jmp_buf jmpbuffer; static jmp_buf jmpbuffer2; static int globval; int main(void) { int autoval; register int regival; volatile int volaval; static int statval; globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5; if (setjmp(jmpbuffer2) == 2) { printf("\n in main,after longjmp:\n"); printf("globval = %d, autoval = %d, regival = %d," " volaval = %d, statval = %d\n", globval, autoval, regival, volaval, statval); exit(0); } /* * Change variables after setjmp, but before longjmp. */ globval = 95; autoval = 96; regival = 97; volaval = 98; statval = 99; f1(autoval, regival, volaval, statval); /* never returns */ exit(0); } static void f1(int i, int j, int k, int l) { printf("in f1():\n"); printf("globval = %d, autoval = %d, regival = %d," " volaval = %d, statval = %d\n", globval, i, j, k, l); if(setjmp(jmpbuffer) != 0){ printf("in f1, after longjmp!\n"); longjmp(jmpbuffer2,2); exit(0); } f2(); } static void f2(void) { printf("in f2\n"); longjmp(jmpbuffer, 1); }
相應的輸出:異常
in f1(): globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99 in f2 in f1, after longjmp! in main,after longjmp: globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99