五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

C/C++編程筆記:C 語言中 setjmp 和 longjmp,教你正確函數(shù)內(nèi)跳轉(zhuǎn)!

2020-05-08 21:03 作者:C語言編程__Plus  | 我要投稿

在 C 語言中,我們不能使用goto語句來跳轉(zhuǎn)到另一個函數(shù)中的某個label處;但提供了兩個函數(shù)——setjmplongjmp來完成這種類型的分支跳轉(zhuǎn)。后面我們會看到這兩個函數(shù)在處理異常上面的非常有用。


setjmp 和 longjmp 使用方法

我們都知道要想在一個函數(shù)內(nèi)進行跳轉(zhuǎn),可以使用goto語句(不知怎么該語句在中國學(xué)生眼中就是臭名昭著,幾乎所有國內(nèi)教材都一刀切地教大家盡量不要使用它,但在我看來,這根本不是語言的問題,而是使用該語言的人,看看 Linux 內(nèi)核中遍地是 goto 語句的應(yīng)用吧?。?,但如果從一個函數(shù)內(nèi)跳轉(zhuǎn)到另一個函數(shù)的某處,goto 是不能完成的,那該如何實現(xiàn)呢?

函數(shù)間跳轉(zhuǎn)原理

我們要實現(xiàn)的一個GOTO語句(我自己定義的),能實現(xiàn)在函數(shù)間進行任意跳轉(zhuǎn),如下例,在函數(shù) g() 中有條語句GOTO Label;可以跳轉(zhuǎn)到 f() 函數(shù)的Label:標(biāo)簽所指向的位置,那么我們該如何實現(xiàn)呢?


首先我們要知道,實現(xiàn)這種類型的跳轉(zhuǎn),和操作系統(tǒng)中任務(wù)切換的上下文切換有點類似,我們只需要恢復(fù) Label 標(biāo)簽處函數(shù)上下文即可。函數(shù)的上下文包括以下內(nèi)容:

(1)函數(shù)棧幀,主要是棧幀指針BP和棧頂指針SP

(2)程序指針PC,此處為指向 Label 語句的地址

(3)其它寄存器,這是和體系相關(guān)的,在 x86 體系下需要保存有的 AX/BX/CX 等等 callee-regs。

這樣,在執(zhí)行GOTO Label;這條語句,我們恢復(fù) Label 處的上下文,即完成跳轉(zhuǎn)到 Label 處的功能。

如果你讀過 Linux 操作系統(tǒng)進程切換的源碼,你會很明白 Linux 會把進程的上下文保存在 task_struct

結(jié)構(gòu)體中,切換時直接恢復(fù)。這里我們也可以這樣做,將 Label 處的函數(shù)上下文保存在某個結(jié)構(gòu)體中,但執(zhí)行到 GOTO Label

語句時,我們從該結(jié)構(gòu)體中恢復(fù)函數(shù)的上下文。

這就是函數(shù)間進行跳轉(zhuǎn)的基本原理,而 C 語言中 setjmp 和 longjmp 就為我們完成了這樣的保存上下文和切換上下文的工作。

函數(shù)原型


setjmp 函數(shù)的功能是將函數(shù)在此處的上下文保存在 jmp_buf 結(jié)構(gòu)體中,以供 longjmp 從此結(jié)構(gòu)體中恢復(fù)。

(1)參數(shù) env 即為保存上下文的 jmp_buf 結(jié)構(gòu)體變量;

(2)如果直接調(diào)用該函數(shù),返回值為 0; 若該函數(shù)從 longjmp 調(diào)用返回,返回值為非零,由 longjmp 函數(shù)提供。根據(jù)函數(shù)的返回值,我們就可以知道 setjmp 函數(shù)調(diào)用是第一次直接調(diào)用,還是由其它地方跳轉(zhuǎn)過來的。


longjmp 函數(shù)的功能是從 jmp_buf 結(jié)構(gòu)體中恢復(fù)由 setjmp 函數(shù)保存的上下文,該函數(shù)不返回,而是從 setjmp 函數(shù)中返回。

(1)參數(shù) env 是由 setjmp 函數(shù)保存過的上下文。

(2)參數(shù) val 表示從 longjmp 函數(shù)傳遞給 setjmp 函數(shù)的返回值,如果 val 值為0, setjmp 將會返回1,否則返回 val。

(3)longjmp 不直接返回,而是從 setjmp 函數(shù)中返回,longjmp 執(zhí)行完之后,程序就像剛從 setjmp 函數(shù)返回一樣。

簡單實例

下面是個簡單的例子,雖然還只是函數(shù)內(nèi)跳轉(zhuǎn),但足以說明這兩個函數(shù)的功能了。


運行該程序得到的結(jié)果為:


C 語言異常處理

Java、C# 等面向?qū)ο笳Z言中都有異常處理的機制,如下就是典型的 Java 中異常處理的代碼,兩個數(shù)相除,如果被除數(shù)為0拋出異常,在函數(shù) f() 中可以獲取該異常并進行處理:


在 C 語言中雖然沒有類似的異常處理機制,但是我們可以使用 setjmp 和 longjmp 來模擬實現(xiàn)該功能,這也是這兩個函數(shù)的一個重要的應(yīng)用:


如果復(fù)雜一點,可以根據(jù) longjmp 傳遞的返回值來判斷各種不同的異常,來進行區(qū)別的處理,代碼結(jié)構(gòu)如下:

希望對大家有幫助~

學(xué)習(xí)C/C++可以關(guān)注UP!

想要學(xué)習(xí)C/C++基礎(chǔ)知識和項目知識,可以關(guān)注UP上傳的視頻,希望對你有幫助,會持續(xù)更新哦~


C/C++編程筆記:C 語言中 setjmp 和 longjmp,教你正確函數(shù)內(nèi)跳轉(zhuǎn)!的評論 (共 條)

分享到微博請遵守國家法律
榕江县| 北流市| 安达市| 吉林市| 建昌县| 上栗县| 延津县| 乐平市| 上饶县| 霍州市| 客服| 永定县| 金湖县| 芮城县| 垣曲县| 霞浦县| 怀化市| 图木舒克市| 阳信县| 长春市| 磴口县| 嵊州市| 高台县| 孝昌县| 德清县| 平江县| 安陆市| 苏州市| 承德市| 灌阳县| 津市市| 汝阳县| 肥城市| 开化县| 昌平区| 南昌市| 巴彦县| 汉源县| 建德市| 阜平县| 岐山县|