简介
setjmp.h 头文件定义了宏 setjmp()、函数 longjmp() 和变量类型 jmp_buf,该变量类型会绕过正常的函数调用和返回规则。
那么我们今天要看的是非局部跳转语句中---setjmp和longjmp函数。前面说的非局部就是指不是C语言中的goto这种的,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。
setjmp()函数声明
int setjmp(jmp_buf environment)
(1)它是创建本地的jmp_buf缓冲区并且初始化,用于将来跳转回此处。这个子程序保存程序的调用环境于env参数所指的缓冲区,env将被longjmp使用。如果是从setjmp直接调用返回,setjmp返回值为0。如果是从longjmp恢复的程序调用环境返回,setjmp返回非零值。
(2)声明中的environment -- 这是一个类型为 jmp_buf 的用于存储环境信息的对象。
返回值
对于setjmp()宏可能不只返回一次。第一次,在直接调用它时,它总是返回零。当调用 longjmp 时带有设置的环境信息,这个宏会再次返回,此时它返回的值会传给 longjmp 作为第二个参数。
下面的就用实际例子来看 setjmp() 宏的用法。
例如:
#include
#include static jmp_buf buf;
void second(void)
{
printf("second\n"); // 打印
longjmp(buf,1); // 跳回setjmp的调用处 - 使得setjmp返回值为1
}
void first(void)
{
second();
printf("first\n"); // 不可能执行到此行
}
int main()
{
if ( ! setjmp(buf) )
{
first(); // 进入此行前,setjmp返回0
} else { // 当longjmp跳转回,setjmp返回1,因此进入此行 printf("main\n"); // 打印 } return 0;
}
让我们编译并运行上面的程序,这将产生以下结果:
second
main
了解完setjmp()函数以后,再来看看longjmp()函数
longjmp()函数的声明:
void longjmp(jmp_buf environment, int value)
(1)longjmp()函数他就是恢复最近次调用 setjmp() 宏时保存的环境,jmp_buf 参数的设置是由之前调用 setjmp() 生成的。
(2)environment -- 这是一个类型为 jmp_buf 的对象,包含了调用 setjmp 时存储的环境信息。value -- 这是 setjmp 表达式要判断的值。
(3)该函数不返回任何值。
下面演示 longjmp() 函数的用法。
#include #include
static jmp_buf buf;
void second(void) {
printf("second\n"); // 打印
longjmp(buf,1); // 跳回setjmp的调用处 - 使得setjmp返回值为1}
void first(void) {
second();
printf("first\n"); // 不可能执行到此行}
int main() {
if ( ! setjmp(buf) ) {
first(); // 进入此行前,setjmp返回0
} else { // 当longjmp跳转回,setjmp返回1,因此进入此行
printf("main\n"); // 打印
}
return 0;}
让我们编译并运行上面的程序,这将产生以下结果:
second
main
上面这些都是你需要掌握的,这两个函数结合着学,这样学习效果也是不错的