博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言中的随意跳转
阅读量:5966 次
发布时间:2019-06-19

本文共 2755 字,大约阅读时间需要 9 分钟。

C语言中有一个很不常用的头文件:setjmp.h。

这个头文件是C语言底层实现的,不像math.h里面的函数都是纯C语言实现的。

setjmp.h包含两个函数:

  • longjmp 跳转到某个位置
  • setjmp 设置一个跳转位置

setjmp用于设置一个语句标号,longjmp用于跳到某个语句标号。

这两个函数一结合,功能比goto还要强大。

#include 
/* printf */#include
/* jmp_buf, setjmp, longjmp */main(){ jmp_buf env; int val; val=setjmp(env); printf ("val is %d\n",val); if (!val) longjmp(env, 1); return 0;}

输出为

val is 0

val is 1

setjmp函数的返回值有两种情况:

  • 如果是创建“语句标号”,总是返回0,表示创建“语句标号”成功
  • 如果是被longjmp跳转来的,那么返回值就表示“从何处跳转来的”,这个值也是一个int,是longjmp跳转来的时候指定的

longjmp的两个参数:

  • env参数表示想要跳转到的“语句标号”
  • number参数表示“我是谁”,也就是主跳函数的ID,这个ID最终会被setjmp返回,用来判断跳转来源。

下面再举一个例子:在学校每天都是吃饭、学习、睡觉,周而复始、永不停息。用C语言如何描述这个过程呢?

#include
#include
#include
using namespace std;jmp_buf eat_jump, sleep_jump, study_jump;void eat() { int value = setjmp(eat_jump); if (value == 0)return; cout << "新的一天开始了,吃饭、学习、睡觉" << endl; system("@pause"); cout << "eat" << endl; longjmp(study_jump, 1);}void sleep() { int value = setjmp(sleep_jump); if (value == 0)return;//如果是第一次创建,那就不要执行了 cout << "sleep" << endl; longjmp(eat_jump, 1);}void study() { int value = setjmp(study_jump); if (value == 0)return; cout << "study" << endl; longjmp(sleep_jump, 1);}int main() { sleep(); study(); eat(); longjmp(eat_jump, 1);}

输出为:

新的一天开始了,吃饭、学习、睡觉请按任意键继续. . .eatstudysleep新的一天开始了,吃饭、学习、睡觉请按任意键继续. . .eatstudysleep新的一天开始了,吃饭、学习、睡觉请按任意键继续. . .eatstudysleep新的一天开始了,吃饭、学习、睡觉请按任意键继续. . .eatstudysleep新的一天开始了,吃饭、学习、睡觉请按任意键继续. . .eatstudysleep新的一天开始了,吃饭、学习、睡觉请按任意键继续. . .eatstudysleep新的一天开始了,吃饭、学习、睡觉请按任意键继续. . .

这样的生活太单调了,最起码应该是随机一些:我吃了饭,可能睡觉也可能学习;我睡了觉,可能吃饭也可能学习;我学了习,可能吃饭也可能睡觉。

#include
#include
#include
using namespace std;jmp_buf eat_jump, sleep_jump, study_jump;const int EAT = 1, SLEEP = 2, STUDY = 3;void eat() { int value = setjmp(eat_jump); if (value == 0)return; cout << "新的一天开始了,吃饭、学习、睡觉" << endl; system("@pause"); cout << "eat after " << (value == SLEEP ? "sleep" : "study") << endl; if (rand() % 2 == 0) longjmp(study_jump, EAT); else longjmp(sleep_jump, EAT);}void sleep() { int value = setjmp(sleep_jump); if (value == 0)return;//如果是第一次创建,那就不要执行了 cout << "sleep after " << (value == EAT ? "eat" : "study") << endl; if (rand() % 2 == 0) longjmp(eat_jump, SLEEP); else longjmp(study_jump, SLEEP);}void study() { int value = setjmp(study_jump); if (value == 0)return; cout << "study after " << (value == EAT ? "eat" : "sleep") << endl; if (rand() % 2 == 0) longjmp(sleep_jump, STUDY); else longjmp(eat_jump, STUDY);}int main() { srand(0); sleep(); study(); eat(); longjmp(eat_jump, 1);}

goto虽好,可不要贪杯呀。

转载地址:http://aqmax.baihongyu.com/

你可能感兴趣的文章
git改密码出现授权问题
查看>>
ORA-02266: 表中的唯一/主键被启用的外键引用
查看>>
Django的POST请求时因为开启防止csrf,报403错误,及四种解决方法
查看>>
day-6 and day-7:面向对象
查看>>
CSU Double Shortest Paths 湖南省第十届省赛
查看>>
webgl像机世界
查看>>
php正则怎么使用(最全最细致)
查看>>
javascript数学运算符
查看>>
LC.155. Min Stack(非优化,两个stack 同步 + -)
查看>>
交互设计[3]--点石成金
查看>>
SCCM TP4部署Office2013
查看>>
Android创建启动画面
查看>>
Linux中date命令的各种实用方法--转载
查看>>
mysqld -install命令时出现install/remove of the service denied错误的原因和解决办法
查看>>
苹果企业版帐号申请记录
查看>>
C++ Error: error LNK2019: unresolved external symbol
查看>>
Bitmap 和Drawable 的区别
查看>>
Java操作mongoDB2.6的常见API使用方法
查看>>
如何给服务器设置邮件警报。
查看>>
CEF js调用C#封装类含注释
查看>>