setjmp與longjmp函式用法
阿新 • • 發佈:2018-12-14
C語言中,在一個函式中執行跳轉,我們使用goto語句。而執行從一個函式跳轉到另一個函式,我們使用setjmp和longjmp函式的組合。
include <setjmp.h>
Int setjmp(jmp_buf env);
返回值:若直接呼叫則返回0,若從longjmp呼叫返回則返回非0值
Void longjmp(jmp_buf env,int val);
使用方法 我們在希望返回的位置呼叫setjmp,此位置在main函式中,因為直接呼叫該函式,所以其返回值為0。setjmp引數env的型別是一個特殊的型別jmp_buf,這一資料型別是某種形式的陣列,其中存放在呼叫longjmp時能用來恢復棧狀態的所有資訊。因為需要在另一個函式中引用env變數,所以規範的處理方式是將env變數定義為全域性變數。
當檢查到一個錯誤時,則以兩個引數呼叫longjmp函式,第一個就是在呼叫setjmp時所用的env,第二個引數是具有非0值的val,它將成為從setjmp處返回的值。使用第二個引數的原因是對於一個setjmp可以有多個longjmp。
通俗的解釋就是:先呼叫setjmp,用變數envbuf記錄當前的位置,然後呼叫longjmp,返回envbuf所記錄的位置,並使setjmp的返回值為val。當時用longjmp時,envbuf的內容被銷燬了。其實這裡的“位置”一詞真正的含義是棧定指標。 longjmp 是不直接返回的,而是從 setjmp 函式中返回,longjmp 執行完之後,程式就像剛從 setjmp 函式返回一樣。 一個簡單的例項
#include<stdio.h>
#include<setjmp.h>
jmp_buf buf;
void hello()
{
printf("hello\n");
longjmp(buf,1);
printf("you will see this\n");
}
main()
{
if(setjmp(buf)==0)
{
printf("first \n");
hello();
}
else
printf("ok\n");
}
該函式的輸出是
first
hello
ok
setjmp與longjmp結合使用時,它們必須有嚴格的先後執行順序,也即先呼叫setjmp函式,之後再呼叫longjmp函式,以恢復到先前被儲存的“程式執行點”。否則,如果在setjmp呼叫之前,執行longjmp函式,將導致程式的執行流變的不可預測,很容易導致程式崩潰而退出。