setjmp与longjmp非局部跳转函数的使用
[root@bogon code]# cat c.c #include<stdio.h> #include<setjmp.h> static jmp_buf env;//定义全局变量env void job() { longjmp(env,2);//会返回到setjmp(env)处,且返回值为2 } void work(int argc) { if(argc==1)//没有参数 longjmp(env,1);//返回到setjmp(env)处,返回值为1 job();//有参数调用job() } int main(int argc,char *argv[]) { switch(setjmp(env))//setjmp(env)初始值为0 { case 0: work(argc);//传参数个数过去,argc为1代表没有参数 break; case 1: printf("this is from no parameter work()\n");//不带程序参数的输出 break; case 2: printf("this is from have parameter job()\n");//带程序参数的输出 break; } return 0; } [root@bogon code]# gcc c.c [root@bogon code]# ./a.out this is from no parameter work() [root@bogon code]# ./a.out 32 this is from have parameter job() [root@bogon code]#
现在我们来看一下优化编译器问题
[root@bogon code]# cat c.c #include<stdio.h> #include<stdlib.h> #include<setjmp.h> static jmp_buf env; void work(int a,int b,int c) { longjmp(env,1); } int main(int argc,char *argv[]) { int a; register int b; volatile int c;//将变量声明为volatile,那么编译优化时,该变量的值(300)不会在调用longjmp函数后,重置为setjmp函数调用前的值(30),而其他类型的变量都会重置 a=10; b=20; c=30; if(setjmp(env)==0) { a=100; b=200; c=300; work(a,b,c); } else printf("a is %d\nb is %d\nc is %d\n",a,b,c); return 0; } [root@bogon code]# gcc c.c//没有进行编译优化,所以都没有重置 [root@bogon code]# ./a.out a is 100 b is 200 c is 300 [root@bogon code]# gcc -O c.c//使用选项-O进行编译优化,所以有重置 [root@bogon code]# ./a.out a is 10 b is 20 c is 300 [root@bogon code]#
为了使程序便于维护,还是应当尽量避免使用setjmp和longjmp,不过有时候在恰当的地方,其用处还是很大的,另外我们还应该限制使用goto一样