最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c語言中的局部跳轉及全局跳轉功能

 更新時間:2024年09月19日 10:47:20   作者:標標大人  
本文介紹了C語言中的goto語句,以及如何使用setjmp和longjmp實現跨函數的跳轉,詳細講解了setjmp和longjmp的使用方法和注意事項,以及使用這種全局跳轉后變量狀態(tài)的不確定性,感興趣的朋友一起看看吧

一、前言

在c語言中,當我們在處理某些異常情況的時候,經常會使用goto語句來進行跳轉。goto用起來很方便,但可能很多人都不知道,goto只能在一個函數里面跳轉,并不能夠跨函數跳轉。本文將介紹能夠跨函數跳轉的接口setjmp和longjmp,將圍繞如下內容展開:
1.goto的局限性
2.進程運行時的棧幀結構
3.setjmp和longjmp簡介和使用方法
4.使用了全局跳轉后main中變量的狀態(tài)

二、goto的局限性

goto只能在同一個函數里面跳轉,無法從一個函數跳轉到另一個函數中。如果試圖從一個函數跳轉到另一個函數,則編譯會報錯。參考代碼如下:

/*************************************************************************
        > File Name: goto_test.c
        > Author: conbiao
        > Created Time: 2024年09月13日 星期五 10時47分41秒
 ************************************************************************/
/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include<stdio.h>
/***********************************************************************
 *                              MACRO
 **********************************************************************/
/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/
/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/
void goto_test(void);
/***********************************************************************
* FUNCTION NAME: void goto_test()
 ***********************************************************************
*
* Summary:
*       This function is used to test goto.
*
* Params:
*       NONE.
*
* Return:
*       NONE.
*
***********************************************************************/
void goto_test(void)
{
    int i;
start:
    i = 0;
    printf("%s: start!\n",__func__);
    while(1)
    {
        printf("%s: i = %d\n",__func__,i++);
        if(i > 5)
            goto main_start;
    }
}
/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;
main_start:
    printf("%s: start!\n",__func__);
    goto_test();
    return ret;
}

編譯結果如下:

(2-1)
如果在同一個函數中使用goto,則能夠正常跳轉,代碼如下:

/*************************************************************************
        > File Name: goto_test.c
        > Author: conbiao
        > Created Time: 2024年09月13日 星期五 10時47分41秒
 ************************************************************************/
/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include<stdio.h>
/***********************************************************************
 *                              MACRO
 **********************************************************************/
/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/
/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/
void goto_test(void);
/***********************************************************************
* FUNCTION NAME: void goto_test()
 ***********************************************************************
*
* Summary:
*       This function is used to test goto.
*
* Params:
*       NONE.
*
* Return:
*       NONE.
*
***********************************************************************/
void goto_test(void)
{
    int i;
start:
    i = 0;
    printf("%s: start!\n",__func__);
    while(1)
    {
        printf("%s: i = %d\n",__func__,i++);
        if(i > 5)
            goto start;
    }
}
/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;
main_start:
    printf("%s: start!\n",__func__);
    goto_test();
    return ret;
}

運行結果如下:

(2-2)

三、進程運行時的棧幀結構

在https://editor.csdn.net/md/?articleId=142054973一節(jié)中已經介紹過c程序運行時的存儲空間布局,這其實是一個進程的進程空間結構。其中,??臻g用于存儲程序在運行過程中使用到的臨時變量,在進程空間中,系統(tǒng)為每個函數分配一個棧幀,結構如下:

goto只能在其調用函數的棧幀中跳轉,無法從一個棧幀跳轉到另一個棧幀。

四、setjmp和longjmp

使用setjmp和longjmp能夠實現在棧幀上進行跳躍,其中setjmp用于設置標記,它會保存當前的執(zhí)行環(huán)境(如程序計數器、棧指針等)在調用longjmp后,會恢復之前保存的執(zhí)行環(huán)境,相當于跳轉到setjmp的位置,。

4.1 setjmp

setjmp的函數實現如下:

頭文件:#include <setjmp.h>
函數原型: int setjmp(jmp_buf env);
返回值
如果 setjmp 是直接調用的,它將返回 0。
如果 setjmp 是通過 longjmp 調用的,它將返回 longjmp 的第二個參數(非零值)。
傳入參數
jmp_buf env:這是一個用于存儲執(zhí)行環(huán)境的數組類型。setjmp 會將當前的執(zhí)行環(huán)境保存到這個數組中。

4.2 longjmp

longjmp的函數原型如下:

頭文件: #include <setjmp.h> 函數原型: void longjmp(jmp_buf env, int val);
傳入參數:
jmp_buf env:這是之前由 setjmp 保存的執(zhí)行環(huán)境。
int val:這是 longjmp 返回給 setjmp 的值。通常是一個非零值,用于區(qū)分不同的跳轉點。

4.3 參考代碼

/*************************************************************************
        > File Name: jump_test.c
        > Author: conbiao
        > Created Time: 2024年09月13日 星期五 14時24分11秒
 ************************************************************************/
/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include<stdio.h>
#include<setjmp.h>
/***********************************************************************
 *                              MACRO
 **********************************************************************/
/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/
jmp_buf env;
static int i = 0;
/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/
void func1(void);
/***********************************************************************
* FUNCTION NAME:
 ***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************/
void func1(void)
{
    printf("%s: start!\n",__func__);
    while(i < 8)
    {
        longjmp(env,i++);
    }
}
/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;
    ret = setjmp(env);
    if(ret == 0)
    {
        printf("%s: This is the first call setjump!\n",__func__);
    }
    else
    {
        printf("%s: This is return from longjmp! ret = %d\n",__func__,ret);
    }
    func1();
    return ret;
}

運行結果如下:

(4.3-1)
可見,使用setjmp和longjmp實現了從func1的棧幀跳轉到main函數所在的棧幀的功能。

分析一下上面代碼的執(zhí)行過程,在main函數調用setjmp前,該進程的棧如下:

(4.3-2)
到執(zhí)行func1函數,調用longjmp前,??臻g如下:

(4.3-3)
在setjmp時,會將當前的執(zhí)行環(huán)境信息保存到env中,當執(zhí)行l(wèi)ongjmp時,??臻g會回到4.3-2的情況,func1的棧幀就沒有了。

五、使用全局跳轉后main函數中變量的狀態(tài)

上文已經說明了,使用longjmp會使程序回退到setjmp前的狀態(tài)。那么,如果main函數中在調用setjmp前定義了一個變量,在調用setjmp后改變了這個變量的值,那么當調用longjmp后,該變量的值是調用setjmp前的還是后的呢?
c標準表示這個狀態(tài)是不確定的。
如果希望調用longjmp后該變量的值不變,那么可以將該變量定義為全局變量或者使用static修飾,亦或者使用volatile屬性聲明。

參考資料:

《UNIX環(huán)境高級編程(第3版) (史蒂文斯 (W.Richard Stevens) 拉戈 (Stephen A.Rago))
(Z-Library)》

到此這篇關于c語言中的局部跳轉以及全局跳轉的文章就介紹到這了,更多相關c語言跳轉內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

边坝县| 电白县| 长汀县| 金山区| 衡阳市| 龙井市| 房产| 原阳县| 略阳县| 顺义区| 昌乐县| 雅江县| 通渭县| 景谷| 正宁县| 寻乌县| 南和县| 青阳县| 城市| 时尚| 高要市| 东丰县| 曲阳县| 张掖市| 旬阳县| 清流县| 达孜县| 民和| 平泉县| 新泰市| 北宁市| 平利县| 阿拉善右旗| 崇信县| 通榆县| 茌平县| 馆陶县| 德惠市| 奉贤区| 镶黄旗| 古田县|