微商的自己做网站叫什么软件下载,坪山网站建设行情,做货代用的网站,wordpress机械免费主题setjmp/logjmp的最大用途是错误恢复#xff0c;只要还没有从主函数退出#xff0c;一旦发现一个不可恢复的错误#xff0c;可以把主控制转移大主函数循环#xff0c;并从那从新开始。使用时必须包含头文件setjmp.h setjmp与longjmp结合使用时#xff0c;它们必须…setjmp/logjmp的最大用途是错误恢复只要还没有从主函数退出一旦发现一个不可恢复的错误可以把主控制转移大主函数循环并从那从新开始。使用时必须包含头文件setjmp.h setjmp与longjmp结合使用时它们必须有严格的先后执行顺序也即先调用setjmp函数之后再调用longjmp函数以恢复到先前被保存的“程序执行点”。(从哪儿来回哪儿去否则如果在setjmp调用之前执行longjmp函数将导致程序的执行流变的不可预测很容易导致程序崩溃而退出。 setjmp与logjmp的使用场合: 1.人们对于goto语句的忌讳,很多的专业书籍以及专业人士号召限制goto语句的使用,此时,setjmp与longjmp对goto语句有了很好的替代作用. 2.goto语句有一个局限性,它只能在函数内部跳转.而setjmp与longjmp可以在整个程序全局中跳转,实现长跳转,弥补了goto功能的局限. 3.使用setjmp和longjmp可以捕捉程序中的异常,并采取异常处理机制. 一个例子 使用setjmp,longjmp处理异常. 1 #includestdio.h 2 #includesetjmp.h 3 jmp_buf jumper; 4 void exception(); 5 int deal_exception(); 6 7 main() 8 { 9 int value; 10 int i0; 11 12 valuesetjmp(jumper); 13 if(0value){ 14 exception(); 15 } 16 else{ 17 switch(value) 18 { 19 case 1: 20 printf(解决异常情况[%d]\n,value); 21 break; 22 case 2: 23 printf(解决异常情况[%d]\n,value); 24 break; 25 case 3: 26 printf(解决异常情况[%d]\n,value); 27 break; 28 29 default: 30 31 break; 32 } 33 } 34 } 35 void exception() 36 { 37 int _err_no; 38 if(_err_no3){ 39 printf(出现异常情况[%d]\n,_err_no); 40 longjmp(jumper,_err_no); 41 } 42 return; 43 } 结果 [rootlocalhost test]# gcc error.c [rootlocalhost test]# ./a.out 出现异常情况[3] 解决异常情况[3] [rootlocalhost test]# C语言的try and catch机制 C语言具有的类似try and catch机制,unix下机制也相同。 VC例子 #include stdio.h #include setjmp.h jmp_buf mark; // 保存stack环境的变量 void main(void) { int jmpret; int result; jmpret setjmp( mark ); 1 // 保存当前stack环境到mark变量 if( jmpret 0 ) { scanf(%d,result); if(result0) { longjmp( mark, -1 ); // 发生错误恢复保存的stack环境执行跳转到1处jmpret的值为-1 return; // 此语句永远不被执行 } else { printf(Normal!); return; } } else { // 错误处理 printf(An exception occured!); } } longjmp在Standard C中的说明 1.用longjmp跳转时保证静态变量有正确的值 2.auto变量只保证拥有volatile类型和在setjmp和longjmp之间没有改变的值。 解释 1.静态变量保持为在longjmp调用时的值 2.在setjmp和longjmp之间没有改变的值仍然是原值很简单因为从来就没有改变过 对于一些auto-nonvolatile的值可能在循环中编译器为了优化性能用寄存器来缓存longjmp跳转时没有赋值用volatile修饰能阻止编译器优化。 这两个函数都要包含头文件setjmp.h。而且它们在处理出现在深层函数嵌套的错误情况时很有用处。 setjmp这个函数很有意思虽然是一个函数可是却可以返回两个不同的值。当第一次直接调用setjmp时返回值为0。当从longjmp函数返回时setjmp函数的返回值为longjmp的第二个参数的值。 那么在什么地方调用setjmp呢我们希望当从longjmp函数返回时程序从哪里接着开始运行我们就在哪里调用setjmp。看个小实例你就明白是怎么回事了。 #includestdio.h #includesetjmp.h jmp_buf ebuf; void f2(void); int main(void) { int i; printf(1); isetjmp(ebuf); if(i0) //第一次执行到这里时值为0所以接下来执行f2() { f2(); printf(This will not be printed.); } printf(%d,i); //由于从longjmp返回时i3不执行if所以执行该行 return 0; } void f2(void) { printf(2); longjmp(ebuf,3); //longjmp函数返回回到setjmp的位置使得setjmp返回值为3 } 函数最后的执行结果为123嘻嘻。 longjmp注意 1.不要假象寄存器类型的变量将总会保持不变。在调用longjmp之后通过setjmp所返回的控制流中例程中寄存器类型的变量将不会被恢复。 2.不要使用longjmp函数来实现把控制流从一个中断处理例程中传出除非被捕获的异常是一个浮点数异常。在后一种情况下如果程序通过调用 _fpreset函数来首先初始化浮点数包后它是可以通过longjmp来实现从中断处理例程中返回。 3. 在C程序中小心对setjmp和longjmp的使用应为setjmp和longjmp并不能很好地支持C中面向对象的语义。因此在C程序中使用C提供的异常处理机制将会更加安全。把setjmp和longjmp组合起来原来它这么厉害 使用setjmp时必须使用头文件setjmp.h。 #include setjmp.h jmp_buf jmpbuffer; int setjmp(jmp_buf jmpbuffer); void longjmp(jmp_buf jumpbuffer, int retval); 其中 jmpbuffer 是相关的程序栈的环境上下文。 初始化jmpbuffer之后 setjmp第一次调用的时候会返回 0。 longjmp跳转到setjmp处其中第二个参数retval就是传递给setjmp 作为setjmp的返回值。但是需要主要的是如果retval设置为0 即这样调用的时候 longjmp(jumpbuffer, 0), setjmp会返回1。 函数setjmp()的行为很特别如果直接调用它它便将所有与当前处理器相关的状态信息比如指令指针的内容栈指针等保存到jmp_buf中并返回0。在这种情况下它的表现与一个普通的函数一样。然而如果使用同一个jmp_buf调用longjmp()则函数返回时就好像刚从setjmp()中返回时一样-----又回到刚刚从setjmp()返回的地方。这一次返回值是调用longjmp()时所使用的第二个参数因此可通过这个值判断程序是从longjmp()返回的