首页 > 代码库 > c语言setjmp与longjmp函数

c语言setjmp与longjmp函数

我们都知道在一个函数内进行跳转,可以使用goto语句,但是如果要在函数之间跳转goto是不能完成的。要想完成函数之间的跳转我们需要借助setjmp和longjmp这两个函数连实现,这都包含在头文件setjmp.h中
函数原型:
        1. int setjmp(jmp_buf env):此函数的功能是将函数在此处的上下文保存在jmp_buf结构体中,以供longjmp从此结构体中恢复。参数env即为保存上下文的jmp_buf结构体变量。如果直接调用该函数返回值为0,若该  函数从longjmp调用返回,返回值为非零,用longjmp函数提供。通过该返回值,我们可以判定setjmp是第一次调用还是从其他地方跳转过来的。
        2.void longjmp(jmp_buf env, int val):此函数的功能是从jmp_buf结构体中恢复由setjmp函数保存的上下文。该函数不返回,而是从setjmp函数返回(longjmp不直接返回,而是从setjmp函数中返回,longjmp执行完后,程序就像是从setjmp函数返回一样)。参数env是由setjmp函数保存过的上下文,参数val表示从longjmp函数传递给setjmp函数的返回值,如果val值为0,setjmp将返回1,否则返回val。

例如:

       技术分享

        #该程序运行的结果为:

         i = 0
         i = 2

    在c语言中没有像java、c#等面向对象语言的异常处理机制,但是我们同样可以使用setjmp和longjmp这两个函数来模拟实现该功能。
    例如:   
        #include <stdio.h>
        #include <setjmp.h>

        #define TRY do{ jmp_buf ex_buf__; switch( setjmp(ex_buf__) ){ case 0: while(1){
        #define CATCH(x) break; case x:
        #define FINALLY break; } default:
        #define ETRY } }while(0)
        #define THROW(x) longjmp(ex_buf__, x)

        #define FOO_EXCEPTION (1)
        #define BAR_EXCEPTION (2)
        #define BAZ_EXCEPTION (3)

        int
        main(int argc, char** argv)
        {
           TRY
           {
              printf("In Try Statement\n");
              THROW( BAR_EXCEPTION );
              printf("I do not appear\n");
           }
           CATCH( FOO_EXCEPTION )
           {
              printf("Got Foo!\n");
           }
           CATCH( BAR_EXCEPTION )
           {
              printf("Got Bar!\n");
           }
           CATCH( BAZ_EXCEPTION )
           {
              printf("Got Baz!\n");
           }
           ETRY;

           return 0;
        }
    参考资料
        http://en.wikipedia.org/wiki/Setjmp.h
        http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html
        http://www.cnblogs.com/hazir/p/c_setjmp_longjmp.html

c语言setjmp与longjmp函数