• 非本地跳转


       首先介绍下与非本地跳转的对应的本地跳转,本地跳转指的是类似于goto语句的一系列应用,当设置了标志之后,可以跳到所在函数内部的标号上。然而,本地跳转不能将控制权转移到所在程序的任意地点,不能跨越函数,因此也就有了非本地跳转

     1.非本地跳转是C语言提供的一种用户级的异常控制流的形式,它将控制直接从一个函数转移到另一个当前正在执行的函数,而不需要经过正常的调用-返回序列。

       非本地跳转是通过setjmp和longjmp函数提供的。

     我们来看看函数:

    1 #include <setjmp.h>
    2 //setjmp函数在env缓冲区中保存当前调用环境,以供后面的longjmp使用
    3 int setjmp(jmp_buf env);
    4 int sigsetjmp(sigjmp_buf env,int savesigs);
    5 //sigsetjmp函数和siglongjmp函数是setjmp和longjmp的可以被信号处理程序使用的版本
    6 //longjmp函数从env缓冲区中恢复调用环境,然后触发一个最近一次初始化env的setjmp调用的返回,然后setjmp返回,并带有非零的返回值retval
    7 void longjmp(jmp_buf env,int retval);
    8 void siglongjmp(sigjmp_buf env,int retval);
     返回值:若直接调用则返回0,若从siglongjmp调用返回则返回非0值

       要注意一点,setjmp的返回值不能被赋值给变量。但是可以用在switch语句或者条件语句的测试中

       setjmp函数只调用一次,但是返回多次,一次是当第一次调用setjmp,而调用环境保存在缓冲区env中时,一次是为每个相应的longjmp调用。

       longjmp函数被调用一次但从不返回。

         2.应用

      2.1非本地跳转允许从一个深层嵌套的函数调用中立即返回,通常由检测到某个错误引起的。

      示例代码:

      

     1 #include "csapp.h"
     2  
     3 jmp_buf buf;
     4  
     5 int error1 = 0; 
     6 int error2 = 1;
     7  
     8 void foo(void), bar(void);
     9  
    10 int main() 
    11 {
    12     int rc;
    13  
    14     rc = setjmp(buf);
    15     if (rc == 0)
    16     foo();
    17     else if (rc == 1) 
    18     printf("Detected an error1 condition in foo
    ");
    19     else if (rc == 2) 
    20     printf("Detected an error2 condition in foo
    ");
    21     else
    22     printf("Unknown error condition in foo
    ");
    23     exit(0);
    24 }
    25  
    26 /* deeply nested function foo */
    27 void foo(void) 
    28 {
    29     if (error1)
    30     longjmp(buf, 1); 
    31     bar();
    32 }
    33  
    34 void bar(void) 
    35 {
    36     if (error2)
    37     longjmp(buf, 2); 
    38 }

      2.2使信号处理程序分支到一个特殊的代码位置,而不是返回到被信号到达中断了的指令位置

      示例代码:

      这个代码挺有意思

     1 #include "csapp.h"
     2  
     3 sigjmp_buf buf;
     4  
     5 void handler(int sig) 
     6 {
     7     siglongjmp(buf, 1);
     8 }
     9  
    10 int main() 
    11 {
    12     Signal(SIGINT, handler);
    13  
    14     if (!sigsetjmp(buf, 1)) 
    15 /*The initial call to the sigsetjmp function saves the stack and signal context when the program first starts.*/
    16     printf("starting
    ");
    17     else
    18     printf("restarting
    ");
    19  
    20     while(1) {
    21     Sleep(1);
    22     printf("processing...
    ");
    23     }
    24     exit(0);
    25 }
  • 相关阅读:
    通过DataSet操作XML
    什么是网站流量
    JavaScript总结(2)网页上显示时间
    对xml操作的主要方法
    xml保存图片和读取图片(三)
    SharePoint初探sharepoint 安装宝典(2)
    SharePoint初探启用wss的全文搜索(6)
    转载:sharepoint portal server2003安装小记
    SharePoint初探装完Wss后,无法创建或打开原有Web项目问题(7)
    SharePoint初探SharePoint网站整理(8)
  • 原文地址:https://www.cnblogs.com/blzm742624643/p/9785146.html
Copyright © 2020-2023  润新知