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