setjmp和longjmp提供一种类似goto语句的机制,但它的作用域不局限于同一个函数的作用域之内。这些函数可以用于深层次的嵌套函数调用链。
int setjmp(jmp_buf state);
必须声明一个jmp_buf变量,然后使用setjmp初始化,然后储存处理器状态信息,此时初始化的返回值为0。
void longjmp(jump_buf state, int value);
将保存的状态重新恢复,longjmp使执行流通过再次从setjmp函数返回,从而跳到顶层函数中。
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
jmp_buf restart;
void func1(void);
void func2(void);
int main(int argc, char **argv)
{
if(setjmp(restart)){
printf("program terminate \n");
exit(EXIT_SUCCESS);
}
func1();
printf("program terminate normally\n");
return 0;
}
void func1(void)
{
printf("into func one\n");
func2();
printf("out func one\n");
}
void func2(void)
{
printf("into func two\n");
longjmp(restart, 1);
printf("out func two\n");
}
运行:
setjmp把处理器的状态信息保存到跳转缓冲区,如果变量设置为自动变量,除非没有被修改,否则,是未定义的行为。意思就是保存在内存中的变量,longjmp返回后,保持了longjmp时的值,而在cpu中的值将会退回到setjmp时的值。如下:
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
void change(int r, int s, int a, int v);
jmp_buf state;
int main()
{
//r设置为寄存器变量
register int r = 1;
static int s = 1;
auto int a = 1;
volatile int v = 1;
if(setjmp(state)){
printf("r:%4d s:%4d a:%4d v:%4d\n", r, s, a, v);
return 0;
}
r = s = a = v = 999;
change(r, s, a ,v);
return 1;
}
void change(int r, int s, int a, int v)
{
printf("r:%4d s:%4d a:%4d v:%4d\n", r, s, a, v);
//r寄存器变量,跳转时r是setjmp时的值
longjmp(state, 1);
}
运行:
当setjmp调用函数返回后,可能无法再次调用longjmp。