大家都知道goto语句,但是goto语句是不能跨越函数的,而执行这种类型跳转功能的是函数setjmp和longjmp。这两个函数对于处理发生在很深层嵌套函数调用中的出错情况是非常有用的。
setjmp和longjmp函数又被称为非局部goto。非局部指的是,这不是由普通的C语言goto语句在一个函数内实施跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。
1 函数setjmp和函数longjmp
1.1 函数原型
#include<setjmp.h>
int setjmp(jmp_buf env); //返回值:若直接调用,返回0;若从longjmp返回,则为非0
void longjmp(jmp_buf env,int val);
1.2 参数说明
env:参数env的类型是一个特殊类型jmp_buf。这一数据类型是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。通常将env变量定义为全局变量。
val:就是setjmp从longjmp返回的值,因为一个setjmp可以由多个longjmp。
1.3 示例
下面演示除数为0时返回的例子。
#include<stdio.h>
#include<stdlib.h>
#include<setjmp.h>
jmp_buf jmpbuffer;
double divide(double a,double b){
if(b == 0)
longjmp(jmpbuffer,1);
return a / b;
}
int main(int argc,char* argv[]){
if(setjmp(jmpbuffer) == 0) //直接调用后,返回0,执行以下语句
divide(2,0); //因为divide函数中从longjmp返回1,所以执行else语句
else
printf("error:by 0!\n");
return 0;
}
运行结果:
首先程序进入if语句,因为直接调用setjmp所以会运行if语句下的divide函数,然后i检测到除数为0,则重新返回到setjmp处,因为此时setjmp(jmpbuffer)==1,所以执行else分支。