C和指针 第十六章 标准函数库 本地跳转setjmp.h
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。