C 语言中 setjmp 和 longjmp
在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处;但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转。后面我们会看到这两个函数在处理异常上面的非常有用。
setjmp 和 longjmp 使用方法
我们都知道要想在一个函数内进行跳转,可以使用 goto 语句(不知怎么该语句在中国学生眼中就是臭名昭著,几乎所有国内教材都一刀切地教大家尽量不要使用它,但在我看来,这根本不是语言的问题,而是使用该语言的人,看看 Linux 内核中遍地是 goto 语句的应用吧!),但如果从一个函数内跳转到另一个函数的某处,goto 是不能完成的,那该如何实现呢?
函数间跳转原理
我们要实现的一个 GOTO 语句(我自己定义的),能实现在函数间进行任意跳转,如下例,在函数 g() 中有条语句GOTO Label;
可以跳转到 f() 函数的 Label:
标签所指向的位置,那么我们该如何实现呢?
void f//... //...void g//... //...#include <setjmp.h>int setjmpjmp_bufvoid longjmpjmp_buf int运行该程序得到的结果为:
= 0= 2C 语言异常处理
Java、C# 等面向对象语言中都有异常处理的机制,如下就是典型的 Java 中异常处理的代码,两个数相除,如果被除数为0抛出异常,在函数 f() 中可以获取该异常并进行处理:
double divide(double , double ) throws { if(== 0) throw new Bad ("Cannot / 0"); return / ;}void f() { try { (2, 0); //... } catch () { (.getMessage()); } ("done");}在 C 语言中虽然没有类似的异常处理机制,但是我们可以使用 setjmp 和 longjmp 来模拟实现该功能,这也是这两个函数的一个重要的应用:
static jmp_buf double dividedouble double if== 01return / void fif == 020else "Cannot / 0""done"switch: case 0: //default //... case 1: //exception 1 //... case 2: //exception 2 //... //...关于使用 C 语言来处理异常,可以参见这篇文章,介绍了更多复杂的结构,但无外乎就是 setjmp 和 longjmp 的应用。
参考资料
http://en.wikipedia.org/wiki/Longjmpwww.cs.purdue.edu/homes/cs240/lectures/Lecture-19.pdf