欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言異常處理機制案例講解

 更新時間:2021年07月02日 17:16:41   作者:youlin  
這篇文章主要介紹了C語言異常處理機制案例講解,本文講解了異常處理機制所用的函數(shù)和具體的代碼實現(xiàn)等,以下就是詳細內(nèi)容,需要的朋友可以參考下

異常處理機制:setjmp()函數(shù)與longjmp()函數(shù)

  C標準庫提供兩個特殊的函數(shù):setjmp() 及 longjmp(),這兩個函數(shù)是結構化異常的基礎,正是利用這兩個函數(shù)的特性來實現(xiàn)異常。
所以,異常的處理過程可以描述為這樣:
首先設置一個跳轉(zhuǎn)點(setjmp() 函數(shù)可以實現(xiàn)這一功能),然后在其后的代碼中任意地方調(diào)用 longjmp() 跳轉(zhuǎn)回這個跳轉(zhuǎn)點上,以此來實現(xiàn)當發(fā)生異常時,轉(zhuǎn)到處理異常的程序上,在其后的介紹中將介紹如何實現(xiàn)。
setjmp() 為跳轉(zhuǎn)返回保存現(xiàn)場并為異常提供處理程序,longjmp() 則進行跳轉(zhuǎn)(拋出異常),setjmp() 與 longjmp() 可以在函數(shù)間進行跳轉(zhuǎn),這就像一個全局的 goto 語句,可以跨函數(shù)跳轉(zhuǎn)。
舉個例子,程序在 main() 函數(shù)內(nèi)使用 setjmp() 設置跳轉(zhuǎn),并調(diào)用另一函數(shù)A,函數(shù)A內(nèi)調(diào)用B,B拋出異常(調(diào)用longjmp() 函數(shù)),則程序直接跳回到 main() 函數(shù)內(nèi)使用 setjmp() 的地方返回,并且返回一個值。

-------------------------------------------------------------------------------------------------------------------------

jmp_buf 異常結構

使用 setjmp() 及 longjmp() 函數(shù)前,需要先認識一下 jmp_buf 異常結構。jmp_buf 將使用在 setjmp() 函數(shù)中,用于保存當前程序現(xiàn)場(保存當前需要用到的寄存器的值),jmp_buf 結構在 setjmp.h 文件內(nèi)聲明:

typedef struct
{
unsigned j_sp; // 堆棧指針寄存器
unsigned j_ss; // 堆棧段
unsigned j_flag; // 標志寄存器
unsigned j_cs; // 代碼段
unsigned j_ip; // 指令指針寄存器
unsigned j_bp; // 基址指針
unsigned j_di; // 目的指針
unsigned j_es; // 附加段
unsigned j_si; // 源變址
unsigned j_ds; // 數(shù)據(jù)段
} jmp_buf;

jmp_buf 結構存放了程序當前寄存器的值,以確保使用 longjmp() 后可以跳回到該執(zhí)行點上繼續(xù)執(zhí)行。

-------------------------------------------------------------------------------------------------------------------------

  setjmp() 與 longjmp() 函數(shù)詳細說明

setjmp() 與 longjmp() 函數(shù)原型如下:

  void _Cdecl longjmp(jmp_buf jmpb, int retval);

  int _Cdecl setjmp(jmp_buf jmpb);

_Cdecl 聲明函數(shù)的參數(shù)使用標準C的進棧方式(由右向左)壓棧,_Cdecl 是C語言的一種調(diào)用約定,除此以外,PASCAL 也是調(diào)用約定之一。C標準調(diào)用約定(_Cdecl)所聲明的函數(shù)不自動清除堆棧,這一事務由調(diào)用者自行負責——這也是C可以支持不固定個數(shù)的參數(shù)的原因。此外,這一調(diào)用約定將在函數(shù)名前添加一個下劃線字符,如某一函數(shù)聲明為:

int cdecl DoSomething(void);

編譯時將自動為 DoSomething 加上下劃線前綴,即函數(shù)名變?yōu)椋? _DoSomething。

setjmp() 與 longjmp() 函數(shù)都使用了 jmp_buf 結構作為形參,它們的調(diào)用關系是這樣的:

首先調(diào)用 setjmp() 函數(shù)來初始化 jmp_buf 結構變量 jmpb,將當前CPU中的大部分影響到程序執(zhí)行的寄存器的值存入 jmpb,為 longjmp() 函數(shù)提供跳轉(zhuǎn),setjmp() 函數(shù)是一個有趣的函數(shù),它能返回兩次,它應該是所有庫函數(shù)中唯一一個能返回兩次的函數(shù),第一次是初始化時,返回零,第二次遇到 longjmp() 函數(shù)調(diào)用后,longjmp() 函數(shù)使 setjmp() 函數(shù)發(fā)生第二次返回,返回值由 longjmp() 的第二個參數(shù)給出(整型,這時不應該再返回零)。

在使用 setjmp() 初始化 jmpb 后,可以其后的程序中任意地方使用 longjmp() 函數(shù)跳轉(zhuǎn)會 setjmp() 函數(shù)的位置,longjmp() 的第一個參數(shù)便是 setjmp() 初始化的 jmpb,若想跳轉(zhuǎn)回剛才設置的 setjmp() 處,則 longjmp() 函數(shù)的第一個參數(shù)是 setjmp() 所初始化的 jmpb 這個異常,這也說明一件事,即 jmpb 這個異常,一般需要定義為全局變量,否則,若是局部變量,當跨函數(shù)調(diào)用時就幾乎無法使用(除非每次遇到函數(shù)調(diào)用都將 jmpb 以參數(shù)傳遞,然而明顯地,是不值得這樣做的);longjmp() 函數(shù)的第二個參數(shù)是傳給 setjmp() 的第二次返回值,這在介紹 setjmp() 函數(shù)時已經(jīng)介紹過。

異常處理過程

先來對比(參考)一下 C++ 的異常處理,C++ 在語言層上便添加了異常處理機制,使用 try 塊來包含那些可能出現(xiàn)錯誤的代碼,你可以在 try 塊代碼中拋出異常,C++ 使用 throw 來拋出異常。拋出異常后,將轉(zhuǎn)到異常處理程序中執(zhí)行,C++ 使用 catch 塊來包含那些處理異常的代碼,catch 塊可以接收不同類型的異常。需要說明的是,throw 一般不在 try 塊內(nèi)的代碼中拋出異常,try 塊內(nèi)的代碼調(diào)用了別的函數(shù),如函數(shù)A,函數(shù)A 又調(diào)用了函數(shù) B,throw 可以在函數(shù)B中拋出異常,或者更深的函數(shù)調(diào)用層,無論如何,只要有異常拋出,程序?qū)⑥D(zhuǎn)到 catch 處執(zhí)行。

C中如何實現(xiàn),或者明確地說是模擬這一功能?

下面介紹的是一些簡單的方法。

現(xiàn)在假設 longjmp() 第二個值為1,即 setjmp() 第二次將返回1。我們使用一組簡單的宏來替代 setjmp() 和 longjmp() 以便使用:

首先定義一個全局的異常:

jmp_buf Jump_Buffer;

因為 setjmp() 第一次調(diào)用初始化后返回0,第二次返回非0,可以這樣定義一個宏使得它功能接近于 C++ 的 try。

#define try if(!setjmp(Jump_Buffer))

當 setjmp() 函數(shù)第一次0 時,取非為真,則執(zhí)行 try 塊內(nèi)的代碼,如:

try{

Test();

}

當因為調(diào)用 longjmp() 拋出異常而導致 setjmp() 第二次返回時(程序?qū)D(zhuǎn)到 setjmp() 函數(shù)處返回,這時,這時應該執(zhí)行的是異常處理代碼。longjmp() 使 setjmp() 函數(shù)返回非0,if(!setjmp(JumpBuffer)) 中將值取非則為假,是以,異常處理放在其后應該使用一個 else:

#define catch else

如此看起來便跟 C++ 相似了,setjmp() 函數(shù)的第二次返回導致 if() 中表達式值為假,剛好使 catch 塊得以執(zhí)行,如:

try{

Test();

}catch{

puts("Error");

}

實現(xiàn)如 C++ 的 throw 語句,事實上以宏替換 longjmp(jmp_buf, int) 的調(diào)用:

#define throw longjmp(Jump_Buffer, 1)

下面的例程解釋如何使用這些宏:
-------------------------------------------------------------------------------------------------------------------------

#include"stdio.h"
#include"conio.h"
#include"setjmp.h"
jmp_buf Jump_Buffer;
#define try if(!setjmp(Jump_Buffer))
#define catch else
#define throw longjmp(Jump_Buffer,1)
int Test(int T)
{
    if(T>100)
        throw;
    else
          puts("OK.");
    return 0;
}
int Test_T(int T)
{
    Test(T);
    return 0;
}
int main()
{
    int T;
    try{
          puts("Input a value:");
          scanf("%d",&T);
          T++;
          Test_T(T);
      } catch{
          puts("Input Error!");
      }
    getch();
    return 0;
}

到此這篇關于C語言異常處理機制案例講解的文章就介紹到這了,更多相關C語言異常處理機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C語言創(chuàng)建和操作單鏈表數(shù)據(jù)結構的實例教程

    C語言創(chuàng)建和操作單鏈表數(shù)據(jù)結構的實例教程

    這篇文章主要介紹了C語言創(chuàng)建和操作單鏈表數(shù)據(jù)結構的實例教程,講解使用C語言實現(xiàn)鏈表結構時指針的使用,需要的朋友可以參考下
    2016-04-04
  • 淺析iterator與指針的區(qū)別

    淺析iterator與指針的區(qū)別

    指針和iterator都支持減法運算,指針-指針得到的是兩個指針之間的距離,迭代器-迭代器得到的是兩個迭代器之間的距離
    2013-10-10
  • C++?棧和隊列的實現(xiàn)超詳細解析

    C++?棧和隊列的實現(xiàn)超詳細解析

    棧和隊列,嚴格意義上來說,也屬于線性表,因為它們也都用于存儲邏輯關系為?"一對一"?的數(shù)據(jù),但由于它們比較特殊,因此將其單獨作為一章,做重點講解
    2022-03-03
  • Qt QFtp客戶端實現(xiàn)上傳下載文件

    Qt QFtp客戶端實現(xiàn)上傳下載文件

    本文主要介紹了Qt QFtp客戶端實現(xiàn)上傳下載文件,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • C語言庫函數(shù)qsort及bsearch快速排序算法使用解析

    C語言庫函數(shù)qsort及bsearch快速排序算法使用解析

    這篇文章主要為大家介紹了C語言庫函數(shù)qsort及bsearch快速排序算法的使用示例解析
    2022-02-02
  • 淺析C語言調(diào)試器GDB和LLDB的使用方法

    淺析C語言調(diào)試器GDB和LLDB的使用方法

    這篇文章主要介紹了C語言調(diào)試器GDB和LLDB的使用方法,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-12-12
  • C++實現(xiàn)簡單24點游戲

    C++實現(xiàn)簡單24點游戲

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡單24點游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C++ Vector用法詳解

    C++ Vector用法詳解

    這篇文章主要介紹了C++ Vector用法詳解,vector是C++標準模版庫(STL,Standard Template Library)中的部分內(nèi)容,本文詳細介紹了它的方方面面,需要的朋友可以參考下
    2015-07-07
  • C++實現(xiàn)簡易通訊錄功能

    C++實現(xiàn)簡易通訊錄功能

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡易通訊錄功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C++將CBitmap類中的圖像保存到文件的方法

    C++將CBitmap類中的圖像保存到文件的方法

    這篇文章主要介紹了C++將CBitmap類中的圖像保存到文件的方法,涉及C++導出資源文件的實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07

最新評論