setjmp和longjmp

源码

/*
* setjmp和longjmp演示
*/
#include <stdio.h>
#include <setjmp.h>

jmp_buf g_jmp;

#define ERR_LESS 1
#define ERR_GREATER 2

void test(int a) {
if (a < 10) {
longjmp(g_jmp, ERR_LESS);
} else if (a > 10) {
longjmp(g_jmp, ERR_GREATER);
}
}

void foo(int a) {
int ret;
ret = setjmp(g_jmp);
switch (ret) {
case 0:
test(a);
break;
case ERR_LESS:
printf("the number is less than 10\n");
break;
case ERR_GREATER:
printf("the number is greater than 10\n");
break;
}
}

int main() {
foo(9);
foo(11);
foo(10);
return 0;
}

分析

int setjmp(jmp_buf)

  保存了当前的堆栈上下文,保存完毕返回0

void longjmp(jmp_buf, int)

  恢复setjmp保存的上下文,且设置setjmp的返回值。

以foo(9)为例分析

1 执行setjmp(g_jmp),保存当前堆栈上下文,ret = 0

2 执行switch语句,跳到case 0,执行test(9),此时longjmp(g_jmp, ERR_LESS)被调用,堆栈状态被恢复到setjmp时的状态,同时ret的值被设置为ERR_LESS

3 又继续执行switch语句,这次跳到case ERR_LESS,打印出错误信息。

4 退出foo函数。

注意

1 使用setjmp不保存寄存器变量

2 在setjmp之前调用longjmp的结果将无法预料

你可能感兴趣的:(setjmp和longjmp)