C中setjmp和longjmp用法

C中提供了goto语法,可以通过goto跳转到函数体内部标记的某一行代码,但是却无法跳出函数之外的任意位置。
为了解决这个限制,C函数库提供了setjmp()和longjmp()函数,它们分别承担非局部位置记录标号和goto作用。

使用这两个函数需要包含头文件<setjmp.h>

int setjmp(jmp_buf env)
建立本地的jmp_buf缓冲区并且初始化,用于将来跳转回此处。这个子程序保存程序的调用环境于env参数所指的缓冲区,env将被longjmp使用。如果是从setjmp直接调用返回,setjmp返回值为0。如果是从longjmp恢复的程序调用环境返回,setjmp返回非零值。

void longjmp(jmp_buf env, int value)
恢复env所指的缓冲区中的程序调用环境上下文,env所指缓冲区的内容是由setjmp子程序调用所保存。value的值从longjmp传递给setjmp。longjmp完成后,程序从对应的setjmp调用处继续执行,如同setjmp调用刚刚完成。如果value传递给longjmp零值,setjmp的返回值为1;否则,setjmp的返回值为value。

当使用longjmp的时候,j的内容被销毁。
用longjmp只能跳回曾经到过的地方。在执行setjmp的地方仍留有一个过程活动记录。从这个角度上讲,longjmp更象是“从何处来”,而不是“要往哪去”。另外,longjmp接受一个额外的整形参数并返回它的值,这可以知道是由longjmp转移到这里的还是从上一条语句执行后自然执行到这里的。

下面demo演示了setjmp和longjmp的使用

//
//  main.c
//  setjmp&&longjmp
//
//  Created by apple on 15/1/28.
//  Copyright (c) 2015年 cc. All rights reserved.
//

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

//记录恢复的位置变量
jmp_buf buf;

void test() {
    
    printf("进入test()函数 \n");
    
    //跳转到buf位置变量记录的位置
    longjmp(buf, 1);
    
    printf("返回test()函数 \n");
}

int main(int argc, const char * argv[]) {

    //setjmp(buf)如果在setjmp本函数体内返回,则返回0
    //如果通过longjmp函数返回,则返回非0值
    
    if (setjmp(buf)) {
        //返回了非0值,通过longjmp函数跳转到setjump函数返回
        printf("main()... setjump()函数通过longjmp返回 \n");
    } else {
        //第一次调用setjmp时,必定正常执行完毕返回,即返回0值
        printf("main()... setjump()函数正常执行完毕返回 \n");
        test();
    }
    
    return 0;
}
打印结果如下。


通过打印的结果可以看出,longjmp函数确实跳转回了记录点的函数体内的那行代码。setjmp和longjmp一般用于异常处理,在发生异常时跳出到标记点,C++中的try catch throw的实现就是在此基础之上的封装,与goto相同,使用longjmp进行跳转破坏了程序的顺序执行结构,并且会造成代码难以理解和调试,所以在C++中不提倡使用这种方式来处理异常,在有些高级的IDE中,使用longjump函数之后的代码都会被标记为警告,比如我使用的XCode就会由警告提示Code will never be executed,代码永远不会被执行。


本文由CC原创总结,如需转载请注明出处:http://blog.csdn.net/oktears/article/details/43232493

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值