setjmp与longjmp

关于C语言的语句跳转,在局部范围内(如同一个函数)可以使用goto语句在栈上跳过若干帧,但是goto语句不能进行跨函数调用。如果要想实现跨函数跳转,就必须要使用setjmp和longjmp组合:

#include <setjmp.h>
int setjmp(jmp_buef nv);
    返回:若直接调用则为0,若从longjmp返回则为非0
void longjmp(jmp_buef env , int val);
    从当前位置跳转到之前调用setjmp的位置

* setjmp(env)设置“jump”点,用正确的程序上下文填充jmp_buf 对象j。这个上下文包括程序存放位置、栈和框架指针,其它重要的寄存器和内存数据。当初始化完jump 的上下文,setjmp()返回0值。对setjmp函数的调用时,会保存程序当前的堆栈环境到env参数中;
* 调用longjmp(env,val)的效果就是一个“长跳转”到由env描述的上下文处(也就是到那原来设置env的setjmp()处)。当作为长跳转的目标而被调用时,setjmp()返回r 或1(如果r设为0的话)。(记住,setjmp()不能在这种情况时返回0,或者说longjmp调用时的参数val不能传0或传1,setjmp返回结果都是1)

注意点
1) 在longjmp后,自动变量和寄存器变量的状态如何?
     对此问题的回答是“看情况”。大多数实现并不滚回这些自动变量和寄存器变量的值,而所有标准则说它们的值是不确定的。如果你有一个自动变量,而又不想使其值滚回,则可定义其为具有volatile属性。全局和静态变量的值在执行longjmp时保持不变。如果要编写一个使用非局部跳转的可移植程序,则必须使用volatile属性。
2) 不要使用longjmp函数来实现把控制流从一个中断处理例程中传出,除非被捕获的异常是一个浮点数异常。在后一种情况下,如果程序通过调用_fpreset函数,来首先初始化浮点数包后,它是可以通过longjmp来实现从中断处理例程中返回。
3) 在C++程序中,小心对setjmp和longjmp的使用,因为setjmp和longjmp并不能很好地支持C++中面向对象的语义。因此在C++程序中,使用C++提供的异常处理机制将会更加安全。 

#include <stdio.h>
#include <setjmp.h>
 
jmp_buf env;
 
void main()
{
    char c;
     for (;; )
    {
        switch (setjmp(env))
        {
            case 0:     // 初始化跳转点
                printf ( "Jump point set.\n");
                break;              
            case 1:     // longjmp可能传入的是0或者1
                ...
                break;
            ...
        }
        process ();
     }
}
 
void process ()
{
    int result;
    // Do something
    ...
    longjmp(env, result);
}


可以用setjmp和longjmp来实现C语言中的异常处理:

http://topic.csdn.net/u/20090701/20/8851f1a5-de7b-4a18-a628-898f035d37bf.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值