小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

C語言再學(xué)習(xí)之 setjmp與longjmp

 lchjczw 2013-01-15

前不久在閱讀Quake3源代碼的時(shí)候,看到一個(gè)陌生的函數(shù):setjmp,一番google和查詢后,覺得有必要針對(duì)setjmp和longjmp這對(duì)函數(shù)寫一篇blog,總結(jié)一下。

setjmp和longjmp是C語言獨(dú)有的,只有將它們結(jié)合起來使用,才能達(dá)到程序控制流有效轉(zhuǎn)移的目的,按照程序員的預(yù)先設(shè)計(jì)的意圖,去實(shí)現(xiàn)對(duì)程序中可能出現(xiàn)的異常進(jìn)行集中處理。

先來看一下這兩個(gè)函數(shù)的定義吧:

setjmp和longjmp的函數(shù)原型在setjmp.h中

函數(shù)原型:

int setjmp(jmp_buf envbuf);

setjmp函數(shù)用緩沖區(qū)envbuf保存系統(tǒng)堆棧的內(nèi)容,以便后續(xù)的longjmp函數(shù)使用。setjmp函數(shù)初次啟用時(shí)返回0值。

 

void longjmp(jmp_buf envbuf, int val);

longjmp函數(shù)中的參數(shù)envbuf是由setjmp函數(shù)所保存的堆棧環(huán)境,參數(shù)val設(shè)置setjmp函數(shù)的返回值。longjmp函數(shù)本身是沒有返回值的,它執(zhí)行后跳轉(zhuǎn)到保存envbuf參數(shù)的setjmp函數(shù)調(diào)用,并由setjmp函數(shù)調(diào)用返回,此時(shí)setjmp函數(shù)的返回值就是val。

 

上面的說明有點(diǎn)拗口,通俗的解釋是:先調(diào)用setjmp,用變量envbuf記錄當(dāng)前的位置,然后調(diào)用longjmp,返回envbuf所記錄的位置,并使setjmp的返回值為val。當(dāng)時(shí)用longjmp時(shí),envbuf的內(nèi)容被銷毀了。其實(shí)這里的“位置”一詞真正的含義是棧定指針。

 

接著讓我們看一個(gè)小例子吧:

#include <stdio.h>
#include <setjmp.h>

jmp_buf buf;

banana(){
    printf("in banana() \n");
    longjmp(buf,1);

    printf("you'll never see this,because i longjmp'd");

}

main()
{
    if(setjmp(buf))
        printf("back in main\n");
    else{
        printf("first time through\n");
        banana();
    }

}

(代碼段引自《C專家編程》:p)

這段代碼的打印結(jié)果是:

first time through

in banana()

back in main

仔細(xì)看一下應(yīng)該更能體會(huì)這對(duì)函數(shù)的作用了吧。

 

setjmp/longjmp的最大用處是錯(cuò)誤恢復(fù),類似try ...catch...

他們的功能比goto強(qiáng)多了,goto只能在函數(shù)體內(nèi)跳來跳去,而setjmp/longjmp可以在到過的所有位置間。

 

從java、.net世界來的兄弟們也許會(huì)很不屑于這對(duì)函數(shù),也許會(huì)覺得這樣的功能會(huì)使代碼的可讀性變差。不過請(qǐng)別忘了,這里是C的世界,每個(gè)世界有每個(gè)世界的哲學(xué),OO只是方法學(xué)的一種,而不是全部。quake3是用C寫的,據(jù)看過其代碼的前輩說,其模塊化非常好,所以這也是我看quake3代碼的初衷。(哦,算了吧,寫游戲不是隨便說說的...)

注:

   我第一次看到setjmp是在quake3代碼的Com_Init中,

/*
=================
Com_Init
=================
*/
void Com_Init( char *commandLine ) {
    char    *s;

    Com_Printf( "%s %s %s\n", Q3_VERSION, CPUSTRING, __DATE__ );

    if ( setjmp (abortframe) ) {
        Sys_Error ("Error during initialization");
    }

....

卡馬克在這里也是當(dāng)catch用的,其中的一句注釋是這么寫的:

jmp_buf abortframe;        // an ERR_DROP occured, exit the entire frame

 

繼續(xù)讀吧,在代碼中慢慢體會(huì)吧...

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多