程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C中setjmp和longjmp用法

C中setjmp和longjmp用法

編輯:關於C語言

C中setjmp和longjmp用法


C中提供了goto語法,可以通過goto跳轉到函數體內部標記的某一行代碼,但是卻無法跳出函數之外的任意位置。
為了解決這個限制,C函數庫提供了setjmp()和longjmp()函數,它們分別承擔非局部位置記錄標號和goto作用。

使用這兩個函數需要包含頭文件

 

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,代碼永遠不會被執行。

\

 

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved