c语言setjmp 与 longjmp(类似try..catch)

本文详细介绍了C语言中的setjmp和longjmp函数,它们用于实现程序控制流的有效转移,通过组合使用,可以实现异常处理。文章通过实例展示了如何利用这些函数在特定位置设置和跳转,特别强调了它们在错误恢复和类似try...catch...结构中的应用,相较于goto语句,setjmp和longjmp提供了更强大的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序员的预先设计的意图,去实现对程序中可能出现的异常进行集中处理。

先来看一下这两个函数的定义吧:

setjmp和longjmp的函数原型在setjmp.h中

函数原型:

int setjmp(jmp_buf envbuf);

setjmp函数用缓冲区envbuf保存系统堆栈的内容,以便后续的longjmp函数使用。setjmp函数初次启用时返回0值

 

void longjmp(jmp_buf envbuf, int val);

longjmp函数中的参数envbuf是由setjmp函数所保存的堆栈环境,参数val设置setjmp函数的返回值。longjmp函数本身是没有返回值的,它执行后跳转到保存envbuf参数的setjmp函数调用,并由setjmp函数调用返回,此时setjmp函数的返回值就是val。

 

上面的说明有点拗口,通俗的解释是:先调用setjmp,用变量envbuf记录当前的位置,然后调用longjmp,返回envbuf所记录的位置,并使setjmp的返回值为val。当时用longjmp时,envbuf的内容被销毁了。其实这里的“位置”一词真正的含义是栈定指针。

 

接着让我们看一个小例子吧:

#include
#include

jmp_buf buf;

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

    printf("you'll never see this,because i longjmp'd");//未执行,因为longjmp会直接跳转到上次的setjmp处。

}

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

}

(代码段引自《C专家编程》:p)

这段代码的打印结果是:

first time through

in banana()

back in main

仔细看一下应该更能体会这对函数的作用了吧。

 

setjmp/longjmp的最大用处是错误恢复,类似try ...catch...

他们的功能比goto强多了,goto只能在函数体内跳来跳去,而setjmp/longjmp可以在到过的所有位置间。

 

 

setjmp() 与 longjmp() 函数都使用了 jmp_buf 结构作为形参,它们的调用关系是这样的:
        首先调用 setjmp() 函数来初始化 jmp_buf 结构变量 jmpb,将当前CPU中的大部分影响到程序执行的积存器存入 jmpb,为 longjmp() 函数提供跳转,setjmp() 函数是一个有趣的函数,它能返回两次,它应该是所有库函数中唯一一个能返回两次的函数,第一次是初始化时,返回零,第二次遇到 longjmp() 函数调用后,longjmp() 函数使 setjmp() 函数发生第二次返回,返回值由 longjmp() 的第二个参数给出(整型,这时不应该再返回零)。
        在使用 setjmp() 初始化 jmpb 后,可以其后的程序中任意地方使用 longjmp() 函数跳转会 setjmp() 函数的位置,longjmp() 的第一个参数便是 setjmp() 初始化的 jmpb,若想跳转回刚才设置的 setjmp() 处,则 longjmp() 函数的第一个参数是 setjmp() 所初始化的 jmpb 这个异常,这也说明一件事,即 jmpb 这个异常,一般需要定义为全局变量,否则,若是局部变量,当跨函数调用时就几乎无法使用(除非每次遇到函数调用都将 jmpb 以参数传递,然而明显地,是不值得这样做的);longjmp() 函数的第二个参数是传给 setjmp() 的第二次返回值

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值