1. 作用:
setjmp()和longjmp() 可以实现非局部控制转移即从一个函数到另外一个函数的跳转。
2. 函数原型:
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env);
setjmp函数设置返回点,保存调用函数的栈环境与env中(相当于保护现场)。
longjmp的作用使用setjmp保存在env中的栈环境信息返回到setjmp的位置,也就是当执行longjmp时程序又回到setjmp处(相当于恢复现场)。
setjmp有两个作用:
1)保存调用函数的栈环境于env中,返回值为0
2)作为longjmp的返回目标地,返回值为longjmp的第二个参数(当第个参数为0时返回值为1)
3. jmp_buf数据类型
typedef struct __jmp_buf_tag jmp_buf[1];
jmp_buf实际是一个数组,内存分配在栈空间中,作为参数传递时是一个指针(指向调用函数的栈帧)。
4. longjmp 返回时变量取值情况
全局变量(静态变量),其值为最后的定值。
自动变量,其值应当维持最后的定值不变但还取决于编译器的优化。
5. 具体实例
/*
* main.c
*
* Created on: 2016年10月10日
* Author: chy
*/
#include <sys/types.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include <setjmp.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#define ERR(t) { fprintf(stderr,t); exit(1)}
jmp_buf env;
int num1;
void test(int a,int b,int c)
{
printf("test() %d %d %d\n",a,b,c);
longjmp(env,1);
}
int main()
{
volatile int num2;
int num3;
num1 = 1,num2 = 3, num3 = 4;
printf("%d %d %d\n",num1,num2,num3);
if(setjmp(env))
{
printf("jmp after data is: num1 = %d num2 = %d num3 = %d \n",num1,num2,num3);
exit(0);
}
num1 = 2,num2 = 6, num3 = 8;
test(num1, num2, num3);
return 0;
}
gcc编译器不使用优化时:
chy@chy-Erazer-Z410:~/xueXi/obj/ecilpse/C/jmp/src$ gcc main.c -o jmp
chy@chy-Erazer-Z410:~/xueXi/obj/ecilpse/C/jmp/src$ ./jmp
1 3 4
test() 2 6 8
jmp after data is: num1 = 2 num2 = 6 num3 = 8
使用-O2优化时:
chy@chy-Erazer-Z410:~/xueXi/obj/ecilpse/C/jmp/src$ gcc -O2 main.c -o jmp
chy@chy-Erazer-Z410:~/xueXi/obj/ecilpse/C/jmp/src$ ./jmp
1 3 4
test() 2 6 8
jmp after data is: num1 = 2 num2 = 6 num3 = 4