在C語言中,用于跳轉的goto語句,只能夠用在同一個函數內部的跳轉。而setjmp 與 longjmp的結合使用,卻可以實現在不同程序之間的跳轉。讓我們先來看一下函數原型吧:
#include <setjmp.h>
int setjmp(jmp_buf env)
|
Returns: 0 if called directly, nonzero if returning from a call to longjmp.
|
void longjmp(jmp_buf env, int val);
|
這兩個函數都要包含頭文件setjmp.h。而且它們在處理出現在深層函數嵌套的錯誤情況時很有用處。
setjmp這個函數很有意思,雖然是一個函數,可是卻可以返回兩個不同的值。當第一次直接調用setjmp時,返回值為0。當從longjmp函數返回時,setjmp函數的返回值為longjmp的第二個參數的值。
那么在什么地方調用setjmp呢?我們希望當從longjmp函數返回時,程序從哪里接著開始運行,我們就在哪里調用setjmp。看個小實例,你就明白是怎么回事了。
#include<stdio.h>
#include<setjmp.h>
jmp_buf ebuf;
void f2(void);
int main(void)
{
int i;
printf("1");
i=setjmp(ebuf);
if(i==0) //第一次執行到這里時,值為0,所以接下來執行f2()
{
f2();
printf("This will not be printed.");
}
printf("%d",i); //由于從longjmp返回時,i=3,不執行if,所以執行該行
return 0;
}
void f2(void)
{
printf("2");
longjmp(ebuf,3); //longjmp函數返回,回到setjmp的位置,使得setjmp返回值為3
}
函數最后的執行結果為123,嘻嘻。
longjmp注意:
1.不要假象寄存器類型的變量將總會保持不變。在調用longjmp之后,通過setjmp所返回的控制流中,例程中寄存器類型的變量將不會被恢復。
2.不要使用longjmp函數來實現把控制流,從一個中斷處理例程中傳出,除非被捕獲的異常是一個浮點數異常。在后一種情況下,如果程序通過調用 _fpreset函數,來首先初始化浮點數包后,它是可以通過longjmp來實現從中斷處理例程中返回。
3.
在C++程序中,小心對setjmp和longjmp的使用,應為setjmp和longjmp并不能很好地支持C++中面向對象的語義。因此在C++程
序中,使用C++提供的異常處理機制將會更加安全。把setjmp和longjmp組合起來,原來它這么厲害!
posted on 2010-08-06 13:29
何克勤 閱讀(625)
評論(0) 編輯 收藏 所屬分類:
C/C++