淺析C語言中的setjmp與longjmp函式

2puT發表於2016-07-23

setjmp和longjmp是C語言獨有的,只有將它們結合起來使用,才能達到程式控制流有效轉移的目的,按照程式設計師的預先設計的意圖,去實現對程式中可能出現的異常進行集中處理。

先來看一下這兩個函式的定義吧:

setjmp和longjmp的函式原型在setjmp.h中

函式原型:
int setjmp(jmp_buf envbuf);

setjmp函式用緩衝區envbuf儲存系統堆疊的內容,以便後續的longjmp函式使用。setjmp函式初次啟用時返回0值。

void longjmp(jmp_buf envbuf, int val);

longjmp函式中的引數envbuf是由setjmp函式所儲存的堆疊環境,引數val設定setjmp函式的返回值。longjmp函式本身是沒有返回值的,它執行後跳轉到儲存envbuf引數的setjmp函式呼叫,並由setjmp函式呼叫返回,此時setjmp函式的返回值就是val。

上面的說明有點拗口,通俗的解釋是:先呼叫setjmp,用變數envbuf記錄當前的位置,然後呼叫longjmp,返回envbuf所記錄的位置,並使setjmp的返回值為val。當時用longjmp時,envbuf的內容被銷燬了。其實這裡的“位置”一詞真正的含義是棧定指標。

接著讓我們看一個小例子吧:

複製程式碼 程式碼如下:

#include <stdio.h>
#include <setjmp.h>

jmp_buf buf;

banana(){
    printf("in banana() \n");
    longjmp(buf,1);

    printf("you'll never see this,because i longjmp'd");

}

main()
{
    if(setjmp(buf))
        printf("back in main\n");
    else{
        printf("first time through\n");
        banana();
    }

}


這段程式碼的列印結果是:
first time through
in banana()
back in main

仔細看一下應該更能體會這對函式的作用了吧。

setjmp/longjmp的最大用處是錯誤恢復,類似try ...catch...

他們的功能比goto強多了,goto只能在函式體內跳來跳去,而setjmp/longjmp可以在到過的所有位置間。

相關文章