事实上C语言也可以实现try-catch机制哦
相关手册
原理
要实现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 <stdio.h>
#include <setjmp.h>
#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语言玩玩吗?