1. 程式人生 > >setjmp與longjmp函式用法

setjmp與longjmp函式用法

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函式,將導致程式的執行流變的不可預測,很容易導致程式崩潰而退出。