异常处理
C 中没有 exception
,所以我们可以用函数返回值来判断错误类型。但有时候又希望在顶层能统一处理错误,让代码更简洁一点。其实第一个想到的可能是 goto
语句,但是 goto
不能跳转到另一个函数的某个 label,不过 C 提供了另外两个函数来完成这个任务:setjmp 和 longjmp。
函数原型
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
例子
第一次调用 setjmp
会返回 0,并且将函数在此处的上下文保存在 jmp_buf
结构体里。调用 longjmp
函数时,jmp_buf 从 setjmp
函数保存的上下文恢复,然后程序跳转到 setjmp
处,setjmp
再次返回,如果 longjmp
设置的 val 为 0,则 setjmp
返回 1,否则返回 val。
#include <stdio.h> /* printf, scanf */
#include <stdlib.h> /* exit */
#include <setjmp.h> /* jmp_buf, setjmp, longjmp */
main()
{
jmp_buf env;
int val;
val = setjmp (env);
if (val) {
fprintf (stderr,"Error %d happened",val);
exit (val);
}
/* code here */
longjmp (env,101); /* signaling an error */
return 0;
}
C 中的宏
宏(macro)就是用 #define
定义的一个符号,在编译预处理时,对程序中所有出现的“宏名”,都会被宏定义时的字符串所替换。一般形式:
#define 宏名 字符串
宏可以分为两类:有参数和无参数。
// 无参数
#define PI 3.1415926
// 有参数
#define MULTIPLY(x, y) (x) * (y)
宏用的好,可以让 C 程序简洁合理很多。
实现 Exception
#include <stdio.h>
#include <setjmp.h>
static jmp_buf ex_buf__;
#define TRY switch(setjmp(ex_buf__)) { case 0:
#define CATCH(x) break; case x:
#define ETRY break; }
#define THROW(x) longjmp(ex_buf__, x)
#define FOO_EXCEPTION (1)
#define BAR_EXCEPTION (2)
#define BAZ_EXCEPTION (3)
void dosomething()
{
printf("I am doing something!\n");
THROW( BAR_EXCEPTION );
printf("I am not reachable\n");
}
int main(int argc, char** argv)
{
TRY
{
dosomething();
}
CATCH( FOO_EXCEPTION )
{
printf("Got Foo!\n");
}
CATCH( BAR_EXCEPTION )
{
printf("Got Bar!\n");
}
CATCH( BAZ_EXCEPTION )
{
printf("Got Baz!\n");
}
ETRY;
printf("everything ends\n");
return 0;
}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于