首页 > 代码库 > setjmp()和longjmp()

setjmp()和longjmp()

1.语言没有异常处理机制,可以使用setjmp和longjmp进行模拟,另外,goto语句不能在函数间跳转,可以使用setjmp和longjmp完成函数间的跳转。

使用setjmp()函数需要包含头文件<setjmp.h>

setjmp()函数用于建立本地的jmp_buf缓冲区并初始化,用于将来跳转到这个地方。

longjmp()函数恢复jmp_buf变量所保存的信息,longjmp()之后返回setjmp()处执行。

1.1使用setjmp处理异常的例子:

# include <stdio.h>
# include <setjmp.h>
# include <stdlib.h>
jmp_buf jmp;
int main(void)
{
	int a,b;
	scanf("%d%d",&a,&b);
	if(setjmp(jmp))
	{
	printf("division error\n");
	system("pause");
	return -1;
	}
	if(b==0)
		longjmp(jmp,1);
	else
		printf("the result is %d\n",a/b);
	system("pause");
return 0;
}

1.2 setjmp用于函数间的跳转:

#include <stdio.h>
#include <setjmp.h>
# include <stdlib.h>
jmp_buf buf;

void f()
{
	int n;
	scanf("%d",&n);
	if(n==1)
		longjmp(buf,1);   //把1送入setjmp的返回值
}

void main(void)
{  
      
   if(setjmp(buf)==1)   
     printf("1 is input\n");
   else 
	  f();
   system("pause");
}

2.setjmp和longjmp对变量的影响

2.1

    setjmp和longjmp的执行过程:

    


2.2  

    setjmp和longjump对全局变量和局部变量的影响:在编译器优化的条件下,局部变量的值会回到setjmp调用之前的取值,而全局变量不会。为了使得变量不受setjmp的影响,可以把这个变量声明为全局变量,也可以加上volatile关键字。这个结果是在ubuntu中编译程序得到的,在其它系统或者编译器情形下,结果可能会有不同。

# include <stdio.h>
# include <stdlib.h>
# include <setjmp.h>
int globalvar;
jmp_buf buf;
int main()
{
	volatile int volvar;
	 int localvar;
	 globalvar=1,volvar=2,localvar=3;
	 if(setjmp(buf))
	 {
	 printf("globalvar is %d,volvar is %d,localvar is %d\n",globalvar,volvar,localvar);   //调用longjmp()之后的变量取值
	 system("pause");
	 return 1;
	 }
	 globalvar=11,volvar=12,localvar=13;
	printf("globalvar is %d,volvar is %d,localvar is %d\n",globalvar,volvar,localvar); //调用longjmp()之前的变量取值
	longjmp(buf,1);
system("pause");
return 0;
}

使用gcc –o test test.c编译,得到以下结果

globalvar is 11,volvar is 12,localvar is 13
globalvaris 11,volvar is 12,localvar is 13

使用gcc –O –o test test.c编译,得到以下结果:

globalvar is 11,volvar is 12,localvar is 13
globalvaris 11,volvar is 12,localvar is 3