免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: KBTiller
打印 上一主题 下一主题

特邀专家在线答疑——名不正则言不顺 一网打尽C语言基本概念 [复制链接]

论坛徽章:
0
191 [报告]
发表于 2011-05-11 19:42 |只看该作者
回复 190# robin10


    好的。不过JUMP之前之后的堆栈变化情况我恐怕谈不好
    我准备一下,把《狂人C》上的相关内容贴一下,敬请大家评论

论坛徽章:
0
192 [报告]
发表于 2011-05-11 19:49 |只看该作者
本帖最后由 KBTiller 于 2011-05-11 19:51 编辑

14.10        非本地跳转setjmp.h
“setjmp.h”中描述了一种数据类型、一个函数和一个类似函数的宏。这些都用于从一个函数“goto”到另一个函数。为了更好地解释其意义,下面借助一种假想的情况来说明。
假设从程序中的某点(S)开始,程序调用函数f1(),而函数f1()又调用f2(),f2()又调用f3()。
正常的运行路线是,执行完f3()返回f2(),从f2()再返回f1(),从f1()再返回S点继续执行。
但是可能有这样的情况,就是在执行f3()的过程中产生了某种“状况”,使得这种循规蹈矩的按照原路返回失去意义(况且这很费时),希望程序能够直接“抄近路”直接返回S点,恢复最初调用时的状态,重新再来进行调用。“setjmp.h”中描述的内容就是为了满足类似这样的“假如再回到从前”式的梦想和目的。
要实现这样的想法,首先需要制作一个路标,并且记录下当时的情境。“jmp_buf”这种数据类型的数据用于记录“当时的情境”。这种类型在本质上是一种数组,但这对于程序没有什么意义。我们只要知道这种类型的数据能够记录程序执行过程中的每一个现场情况就足够了,将来照样恢复现场的工作并不需要我们操心。
全方位地记录执行过程中某个瞬间的现场情况由类型函数的宏setjmp完成。
int setjmp(jmp_buf env);
其中的“env”就是对应于记录现场状况实参的形参。这是个类似函数的宏,姑且就当作函数吧,将会被调用两次。
第一次,在当地设置一个“路标”,以免将来返回的时候“迷路”,并且用“env”记录了现场的所有信息。完成了这件事情,这个函数的返回值为0。
当程序从某个其他函数需要返回到从前标记过的位置时,需要调用longjmp()函数。这个函数的原型是:
void longjmp(jmp_buf env, int val);
返回到当初被标记的位置时,setjmp()这个函数被第二次调用,你完全可以把这次调用看成是拆除“路标”并且用离开时记录的状态信息恢复当初的情境。这次setjmp()的返回值不是0而是调用longjmp()时与“val”对应的实参的哪个值。在调用longjmp()时,即使把对应“val”的实参写成0,setjmp()的返回值也不会是0。
这样,程序就实现了“假如再回到从前”式的愿望。但是也不能指望全部恢复。在setjmp()本地的auto类别的局部变量的值是不确定的,volatile类别的局部变量能保证是发生longjmp()时的值。其他可以保证具有确定值的对象的值也不是恢复到setjmp()时的值,而是发生longjmp()那一时刻的值。
下面的代码示意性地演示了这个过程。
程序代码14-7
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

static jmp_buf hjzt ;// 用于记录环境状态

void f1 ( void );
void f2 ( void );
void f3 ( void );

int main( void )
{

  if ( setjmp ( hjzt ) == 0 )  //这里设置路标
   {
    f1();
   }
  else
   {
    f1();
    puts( "回到main" );
   }

  system("PAUSE");        
  return EXIT_SUCCESS;

}

void f1 ( void )
{
  puts( "进入f1" );
  f2();  
  puts( "回到f1" );
}

void f2 ( void )
{
  puts( "进入f2" );
  f3();  
  puts( "回到f2" );
}

void f3 ( void )
{
  static int zc = 0 ; //用于设置如何返回
  puts( "进入f3" );
  if ( zc == 0 )  //这时直接跳回  
    {
     zc = !zc ;   //下次正常返回
     puts( "离开f3\n" );
     longjmp ( hjzt , 1 ) ; //那个1使下次setjmp(hjzt)的值为1
    }
  else
    {//正常返回
     puts( "离开f3" );
     return ;
    }
}

论坛徽章:
0
193 [报告]
发表于 2011-05-12 09:36 |只看该作者
:wink:

论坛徽章:
1
程序设计版块每日发帖之星
日期:2016-06-04 06:20:00
194 [报告]
发表于 2011-05-12 10:13 |只看该作者
回复 192# KBTiller


   

论坛徽章:
0
195 [报告]
发表于 2011-05-12 14:04 |只看该作者
这个必须占位留名

论坛徽章:
0
196 [报告]
发表于 2011-05-12 17:08 |只看该作者
哪种编译器,什么时候准备接替OS管理计算机资源?
mirnshi 发表于 2011-05-10 20:30



   我没说一定存在这种东西。这只是一种理论可能性,为了更好的理解c库函数。说明c的库函数并不要求其具体实现方法。 至于什么时候接管,那是编译器开发者的事儿。

论坛徽章:
0
197 [报告]
发表于 2011-05-12 21:58 |只看该作者
指针的精髓在于它的有类型和无类型之间的转换吧

论坛徽章:
0
198 [报告]
发表于 2011-05-13 06:48 |只看该作者
指针的精髓在于它的有类型和无类型之间的转换吧
haioulove 发表于 2011-05-12 21:58



    这话怎么讲?C里面有无类型的数据吗?

论坛徽章:
0
199 [报告]
发表于 2011-05-13 14:24 |只看该作者
研究生学习中,主要以C为主,十分想学好C

论坛徽章:
0
200 [报告]
发表于 2011-05-13 21:10 |只看该作者
回复 199# bjtulq


    还是头一次在这个论坛看见在读的研究生,欢迎!请多多发表高见
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP