Unix程序跳转—setjmp与longjmp
2016-05-22 16:31
351 查看
在C语言中,不允许使用跳越函数的goto语句。而执行这种跳转功能的是函数setjmp和longjmp。这两个函数对于处理发生在很深的嵌套函数调用中的出错情况非常有用。换句话说,它可以直接跳跃多层调用回到某个指定的地方。并且在执行跳转时,会抛弃一些栈。
函数原型:
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
返回值:
setjmp若直接调用则返回0,若从longjmp返回则为该函数的第二个参数val。也就是说,setjmp函数一次调用,多次返回。
参数说明:
setjmp的参数env是一个特殊类型jmp_buf。这一数据类型是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。一般情况下,env变量是个全局变量,因为需从另一个函数中引用它(即longjmp、setjmp中都要使用)。
实例程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
static int flag;
static jmp_buf env;
void first();
void second();
void third();
int main()
{
int ret;
scanf("%d", &flag);
ret = setjmp(env);
switch(ret)
{
case 0:
{
printf("this is setjmp\n");
break;
}
case 1:
{
printf("this is return from second\n");
flag = 0;
break;
}
case 2:
{
printf("this is return from third\n");
flag = 0;
break;
}
}
first();
return 0;
}
void first()
{
switch(flag)
{
case 0:
break;
case 1:
second();
break;
case 2:
third();
break;
}
}
void second()
{
longjmp(env, 1);
}
void third()
{
longjmp(env, 2);
}
执行结果:
程序说明:
在first函数中,通过判断全局变量flag来调用second或者third函数,在second和third函数中调用了longjmp,分别返回不同的值。而在setjmp中,我们通过判断返回值来输出信息。一个setjmp函数可以对应多个longjmp函数。从结果中可知,每次运行都打印了两次信息,由此可知,setjmp返回了两次。如果我们将红色部分的代码注释掉,再次编译运行,可以发现程序陷入死循环(因为会不断调用longjmp函数)。
在使用setjmp和longjmp时,一定要注意避免上述的死循环。此外,setjmp与longjmp会被一些信号打断,我们可以使用sigsetjmp和siglongjmp函数组来代替setjmp和longjmp函数组。
函数原型:
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
返回值:
setjmp若直接调用则返回0,若从longjmp返回则为该函数的第二个参数val。也就是说,setjmp函数一次调用,多次返回。
参数说明:
setjmp的参数env是一个特殊类型jmp_buf。这一数据类型是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。一般情况下,env变量是个全局变量,因为需从另一个函数中引用它(即longjmp、setjmp中都要使用)。
实例程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
static int flag;
static jmp_buf env;
void first();
void second();
void third();
int main()
{
int ret;
scanf("%d", &flag);
ret = setjmp(env);
switch(ret)
{
case 0:
{
printf("this is setjmp\n");
break;
}
case 1:
{
printf("this is return from second\n");
flag = 0;
break;
}
case 2:
{
printf("this is return from third\n");
flag = 0;
break;
}
}
first();
return 0;
}
void first()
{
switch(flag)
{
case 0:
break;
case 1:
second();
break;
case 2:
third();
break;
}
}
void second()
{
longjmp(env, 1);
}
void third()
{
longjmp(env, 2);
}
执行结果:
程序说明:
在first函数中,通过判断全局变量flag来调用second或者third函数,在second和third函数中调用了longjmp,分别返回不同的值。而在setjmp中,我们通过判断返回值来输出信息。一个setjmp函数可以对应多个longjmp函数。从结果中可知,每次运行都打印了两次信息,由此可知,setjmp返回了两次。如果我们将红色部分的代码注释掉,再次编译运行,可以发现程序陷入死循环(因为会不断调用longjmp函数)。
在使用setjmp和longjmp时,一定要注意避免上述的死循环。此外,setjmp与longjmp会被一些信号打断,我们可以使用sigsetjmp和siglongjmp函数组来代替setjmp和longjmp函数组。
相关文章推荐
- 程序员必备知识——fork和exec函数详解
- ls 底层源码简单实现
- 不带缓冲的IO的标准输入到标准输出
- 进程环境
- Unix进程控制—wait函数详解
- Unix进程关系—僵死进程与孤儿进程
- JavaString的一些理解
- C++字符及字符串处理函数
- 未来编程形式设想
- wxPython学习笔记(二)
- django第二个项目--使用模板
- python-scrapy-爬取图片笔记
- java 继承练习题4
- [疯狂Java]基础类库:BigDecimal(精确实数)
- c#打印技术
- Netbeans opencv 安装
- java 继承练习题3
- C语言宏操作之反复斟酌
- Xlint以及Java Lint 选项
- Xlint以及Java Lint 选项