浅尝辄止16-C语言实现try-catch

事实上C语言也可以实现try-catch机制哦

相关手册

setjmp(3) longjmp(3)

原理

要实现try-catch,有以下几点需要解决

  • 抓到异常
    可以写一写检查性的代码实现
  • 跳转到catch代码
    函数内部跳转可以用goto,跳到别的函数需要用setjmp(3)和longjmp(3)
    跳转的核心问题就是上下文切换。在同一个函数中,上下文是一样的,所以没有切换上下文的问题。若要跨函数"goto"就要进行上下文切换了,setjmp(3)就是保存被跳转到的位置的上下文的,想要跳转时,就用longjmp(3)。

用法

首先看这2个函数的参数,都有一个jmp_buf env,实际上就是上下文。setjmp(3)调用一下,调用处的上下文就保存在参数中了。longjmp(3)只要把这个保存好的上下文当做参数,就会从setjmp(3)函数返回。奇妙的地方就在这,longjmp(3)自己不返回,而是从setjmp(3)返回。

int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);

代码演示

#include 
#include 

#define try if ((jmp_ret = setjmp(env)) == 0)
#define catchany else if (1)
#define catch(v) else if (jmp_ret == v)

#define ERROR_VALUE1 -1
#define ERROR_VALUE2 -2
#define OK_VALUE 1
static jmp_buf env;
static int jmp_ret;
struct table{
    int value;
    char *name;
};

//4个测试值
static struct table table[4] = {
    {OK_VALUE, "OK_VALUE"},
    {ERROR_VALUE1, "ERROR_VALUE1"},
    {ERROR_VALUE2, "ERROR_VALUE2"},
    {-100, NULL}
};

//被测试的函数,这个函数只有传入OK_VALUE才认为正常,其它情况异常
void test(int value){
    if (value != OK_VALUE){
        longjmp(env, value);
    }
}

int main(int argc, char **argv)
{
    int i;
    //轮流测试4个值
    for (i = 0; i < 4; ++i){
        try{
            test(table[i].value);
            printf("use %s test pass!\n", table[i].name);
        }
        catch(ERROR_VALUE1){
            printf("test fail with error=%s!\n", table[i].name);
        }
        catch(ERROR_VALUE2){
            printf("test fail with error=%s!\n", table[i].name);
        }
        catchany{
            printf("test fail with error=%d!\n", jmp_ret);
        }
    }

    return 0;
}

输出

对测试函数test传入OK_VALUE时,没有抓到异常,传入其它值都抓到了异常。

use OK_VALUE test pass!
test fail with error=ERROR_VALUE1!
test fail with error=ERROR_VALUE2!
test fail with error=-100!

还有什么高级语言的东西可以用C语言玩玩吗?

你可能感兴趣的:(浅尝辄止16-C语言实现try-catch)