使用這兩個函數需要包含頭文件
int setjmp(jmp_buf env)建立本地的jmp_buf緩沖區並且初始化,用於將來跳轉回此處。這個子程序保存程序的調用環境於env參數所指的緩沖區,env將被longjmp使用。如果是從setjmp直接調用返回,setjmp返回值為0。如果是從longjmp恢復的程序調用環境返回,setjmp返回非零值。
void longjmp(jmp_buf env, int value)恢復env所指的緩沖區中的程序調用環境上下文,env所指緩沖區的內容是由setjmp子程序調用所保存。value的值從longjmp傳遞給setjmp。longjmp完成後,程序從對應的setjmp調用處繼續執行,如同setjmp調用剛剛完成。如果value傳遞給longjmp零值,setjmp的返回值為1;否則,setjmp的返回值為value。
當使用longjmp的時候,j的內容被銷毀。
用longjmp只能跳回曾經到過的地方。在執行setjmp的地方仍留有一個過程活動記錄。從這個角度上講,longjmp更象是“從何處來”,而不是“要往哪去”。另外,longjmp接受一個額外的整形參數並返回它的值,這可以知道是由longjmp轉移到這裡的還是從上一條語句執行後自然執行到這裡的。
下面demo演示了setjmp和longjmp的使用
// // main.c // setjmp&&longjmp // // Created by apple on 15/1/28. // Copyright (c) 2015年 cc. All rights reserved. // #include打印結果如下。#include //記錄恢復的位置變量 jmp_buf buf; void test() { printf(進入test()函數 ); //跳轉到buf位置變量記錄的位置 longjmp(buf, 1); printf(返回test()函數 ); } int main(int argc, const char * argv[]) { //setjmp(buf)如果在setjmp本函數體內返回,則返回0 //如果通過longjmp函數返回,則返回非0值 if (setjmp(buf)) { //返回了非0值,通過longjmp函數跳轉到setjump函數返回 printf(main()... setjump()函數通過longjmp返回 ); } else { //第一次調用setjmp時,必定正常執行完畢返回,即返回0值 printf(main()... setjump()函數正常執行完畢返回 ); test(); } return 0; }
通過打印的結果可以看出,longjmp函數確實跳轉回了記錄點的函數體內的那行代碼。setjmp和longjmp一般用於異常處理,在發生異常時跳出到標記點,C++中的try catch throw的實現就是在此基礎之上的封裝,與goto相同,使用longjmp進行跳轉破壞了程序的順序執行結構,並且會造成代碼難以理解和調試,所以在C++中不提倡使用這種方式來處理異常,在有些高級的IDE中,使用longjump函數之後的代碼都會被標記為警告,比如我使用的XCode就會由警告提示Code will never be executed,代碼永遠不會被執行。