C語言異常處理之 setjmp()和longjmp()


異常處理之除0情況

相信大家處理除0時,都會通過函數,然后判斷除數是否為0,代碼如下所示:

double divide(doublea,double b) { const double delta = 0.00000000001;         //由於浮點數不精確,所以需要定義個很小的數  

    if(!((-delta<b)&&(b<delta))) {         return  a/b ; }  else  { return 0; } }

其實這個函數還有瑕疵,當我們調用divide(0,1)時,返回值也是0,在程序運行時,根本無法判斷返回值0是不是除法為0的原因.

 

其實可以通過setjmp()和longjmp()配合使用

描述

  • 和goto很相似, 但是可以從一個函數到另外一個函數的跳轉,常常用在異常處理上面.
  • 這兩個函數需要正確使用,否則會破壞程序順序執行方式
  • 頭文件 #include <setjmp.h>

 

setjmp()和longjmp()

 

int setjmp(jmp_buf env);

將當前上下文保存在jmp_buf結構體中(入棧),並返回0

 

void longjmp(jmp_buf env,int val);

從env變量jmp_buf結構體中恢復setjmp()保存的上下文(出棧,並跳轉)

由於跳轉,所以會從setjmp函數調用點返回,返回值為val

 

 

跳轉機制 (以 mian()函數 divide()函數 為例):

mian()函數 調用了 setjmp(env) ,將上下文(入棧)保存在env中,並返回0.

接着調用 divide()函數 進行除法操作.

進入 setjmp()函數 后,由於發現除法為0,所以使用 longjmp(env,1)函數 ,恢復 setjmp() 保存的上下文,也就是直接返回到了 main()函數 處理 setjmp(env) 的時候,並返回異常值1

 

代碼實現:

#include <stdio.h>
#include <setjmp.h>
jmp_buf env;
double divide(double a,double b) { const double delta = 0.00000000001; //由於浮點數不精確,所以需要定義個很小的數 if(!((-delta<b)&&(b<delta))) { return a/b ; } else { longjmp(env,1); //直接跳轉到23行,ret=setjmp(env)代碼處,並返回異常值(1) return 0; } } int main( ) { int ret; ret=setjmp(env); //手動調用 setjmp(),將返回正常值(0),    if(!ret) //正常操作     {       printf("5/0=%lf\n",divide(5,0));     }     else if(ret==1) //異常操作 {       printf("ERR\n"); } return 0; }

運行打印:

ERR

 

  

缺陷在於:

  • 若需要兩個函數之間跳轉,必然要使用全局變量jmp_buf env
  • 跳轉使得代碼可讀性降低


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM