1.goto只能实现函数内部跳转,而longjmp可以实现函数之间的安全跳转(只有一种情况不安全)
2.setjmp
setjmp, sigsetjmp - save stack context for nonlocal goto
SYNOPSIS
#include <setjmp.h>
int setjmp(jmp_buf env);
①这个函数是保存返回点的信息,保存到jmp_buf这个结构体当中
②他有两个返回值 一个是设置返回点 返回值是 0 ;另外一个是返回了,返回值由longjmp决定 非0
3.longjmp
longjmp, siglongjmp - nonlocal jump to a saved stack context
SYNOPSIS
#include <setjmp.h>
void longjmp(jmp_buf env, int val);
①这个value就决定了返回点的 返回值
②这里可以看出 通常要将jmp_buf这个结构体 定义为全局变量
③If longjmp() is invoked with a second argument of 0, 1 will be
returned instead
4. 一个测试Demo
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
jmp_buf JmpBuf;
void D(void)
{
printf("%s(): Begin\n", __FUNCTION__);
printf("%s(): End\n", __FUNCTION__);
}
void C(void)
{
printf("%s(): Begin\n", __FUNCTION__);
printf("%s(): Call D()\n", __FUNCTION__);
D();
printf("%s(): Return D()\n", __FUNCTION__);
printf("%s(): End\n", __FUNCTION__);
}
void B(void)
{
printf("%s(): Begin\n", __FUNCTION__);
printf("%s(): Call C()\n", __FUNCTION__);
C();
printf("%s(): Return C()\n", __FUNCTION__);
printf("%s(): End\n", __FUNCTION__);
}
void A(void)
{
printf("%s(): Begin\n", __FUNCTION__);
printf("%s(): Call B()\n", __FUNCTION__);
B();
printf("%s(): Return B()\n", __FUNCTION__);
printf("%s(): End\n", __FUNCTION__);
}
int main(int argc, char **argv)
{
printf("%s(): Begin\n", __FUNCTION__);
printf("%s(): Call A()\n", __FUNCTION__);
A();
printf("%s(): Return A()\n", __FUNCTION__);
printf("%s(): End\n", __FUNCTION__);
return 0;
}
结果
进行jmp
void A(void)
{
int res;
printf("%s(): Begin\n", __FUNCTION__);
printf("%s(): Call B()\n", __FUNCTION__);
res = setjmp(JmpBuf);
if(0 == res)
{
B();
printf("%s(): Return B()\n", __FUNCTION__);
printf("%s(): End\n", __FUNCTION__);
}
else
{
printf("%s(): Longjmp from code %d\n", __FUNCTION__, res);
}
}
void D(void)
{
printf("%s(): Begin\n", __FUNCTION__);
printf("%s(): End\n", __FUNCTION__);
longjmp(JmpBuf, 6);
}