C语言中的随意跳转
C语言中有一个很不常用的头文件:setjmp.h。
这个头文件是C语言底层实现的,不像math.h里面的函数都是纯C语言实现的。
setjmp.h包含两个函数:
- longjmp 跳转到某个位置
- setjmp 设置一个跳转位置
setjmp用于设置一个语句标号,longjmp用于跳到某个语句标号。
这两个函数一结合,功能比goto还要强大。
#include <stdio.h> /* printf */
#include <setjmp.h> /* 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<setjmp.h>
#include<stdlib.h>
#include<iostream>
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);
}
输出为:
新的一天开始了,吃饭、学习、睡觉
请按任意键继续. . .
eat
study
sleep
新的一天开始了,吃饭、学习、睡觉
请按任意键继续. . .
eat
study
sleep
新的一天开始了,吃饭、学习、睡觉
请按任意键继续. . .
eat
study
sleep
新的一天开始了,吃饭、学习、睡觉
请按任意键继续. . .
eat
study
sleep
新的一天开始了,吃饭、学习、睡觉
请按任意键继续. . .
eat
study
sleep
新的一天开始了,吃饭、学习、睡觉
请按任意键继续. . .
eat
study
sleep
新的一天开始了,吃饭、学习、睡觉
请按任意键继续. . .
这样的生活太单调了,最起码应该是随机一些:我吃了饭,可能睡觉也可能学习;我睡了觉,可能吃饭也可能学习;我学了习,可能吃饭也可能睡觉。
#include<setjmp.h>
#include<stdlib.h>
#include<iostream>
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虽好,可不要贪杯呀。
C语言中的随意跳转的更多相关文章
- C 语言中函数的跳转
1.同一个函数内,可以使用goto语句: eg: void text_1( void ) { char i=0; a : i++; printf ( " text_1 = %d \r\n& ...
- C语言中内存分配那些事儿
C程序的内存结构 C语言的之所以复杂,首先它的内存模型功不可没.不像某些那样的高级语言只需要在使用对象的时候,用new创建.所有之后的事情,你不需要操心.对于C语言,所有与内存相关的东西,都需要熟悉, ...
- Java语言中的面向对象特性总结
Java语言中的面向对象特性 (总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知 ...
- 2.C语言中的关键字
1.auto 修饰局部变量,编译器默认所有局部变量都是用auto来修饰的,所以在程序中很少见到. 2.static 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...
- C语言中关于对目录的操作
原文地址:C语言中关于对目录的操作 目录的操作不论是在嵌入式产品还是应用软件编程都是必不可少的,不同的开发语言可能略有不同,笔者主要是讨论在Linux平台下对目录的一系列操作: 1.获取当前目录操作: ...
- c语言中函数调用的本质从汇编角度分析
今天下午写篇博客吧,分析分析c语言中函数调用的本质,首先我们知道c语言中函数的本质就是一段代码,但是给这段代码起了一个名字,这个名字就是他的的这段代码的开始地址 这也是函数名的本质,其实也就是汇编中的 ...
- C语言中的转义字符
转义字符 意义 ASCII码值(十进制) \a 响铃(BEL) 007 \b 退格(BS) ,将当前位置移到前一列 008 \f 换页(FF),将当前位置移到下页开头 012 \n 换行(LF) ,将 ...
- C语言中强制数据类型转换(转)
原文地址不详 字符型变量的值实质上是一个8位的整数值,因此取值范围一般是-128-127,char型变量也可以加修饰符unsigned,则unsigned char 型变量的取值范围是0-255(有些 ...
- C语言中的关键字
1.C语言中的关键字都有实际的意义. 2.C语言中的23个关键字如下: char:声明字符型变量. short:声明短整型变量. int:声明整型变量. long:声明长整型变量. float:声明浮 ...
随机推荐
- python机器学习sklearn 岭回归(Ridge、RidgeCV)
1.介绍 Ridge 回归通过对系数的大小施加惩罚来解决 普通最小二乘法 的一些问题. 岭系数最小化的是带罚项的残差平方和, 其中,α≥0α≥0 是控制系数收缩量的复杂性参数: αα 的值越大,收缩量 ...
- Python 通过打码平台实现验证码
在爬虫时,经常遇到登录需要验证码的情况,简单的验证码可以自己解决,复制的验证码需要借助机器学习,有一定的难度.还有一个简单的方案就是采用付费的打码平台. 比如R若快(http://www.ruokua ...
- 大数据开发实战:Stream SQL实时开发二
1.介绍 本节主要利用Stream SQL进行实时开发实战,回顾Beam的API和Hadoop MapReduce的API,会发现Google将实际业务对数据的各种操作进行了抽象,多变的数据需求抽象为 ...
- 添加PMD插件扫描潜在的bug
上一节使用checkstyle来规范你的项目主要解决了代码编码规范问题,比如缩进换行等.这次继续代码健康工具类PMD. 什么是PMD PMD真的不像checkstyle这样的东西所见即所得啊,去官网找 ...
- Jquery的分页插件
Jquery的分页插件, 用起来还不错. 来自: http://flaviusmatis.github.io/simplePagination.js/ 下载地址: https://github.c ...
- lvs 隧道模式请求没有回应的解决
众所周知,lvs共有三种转发机制:NAT,IPTUNNELING与DIRECT ROUTING 我在做隧道模式实验时遇到了一个问题,客户端向虚拟ip(即隧道0的ip)发送请求后,lvs服务器接收到了请 ...
- WDCP安装可选组件的快捷命令
memcache的安装 wget -c http://down.wdlinux.cn/in/memcached_ins.sh chmod 755 memcached_ins.sh ./memcache ...
- robot framework-requests库安装过程问题解决
这几天本想研究下用robotframework+HTTP library (Requests)来做接口测试(http协议), 安装完Requests库后,在RIDE里导入该库时显示是红色,即导入失败( ...
- YII 主题设置
节日不同,站点显示不同主题.就是解决问题. 也制作多套视图. 不是必需为全部页面设置主题,假设没有.就依照正常视图显示 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5 ...
- AndroidStudio 中查看获取MD5和SHA1值以及如何查看手机应用信息以及读取*.db数据库里面数据
查看获取MD5和SHA1值具体操作方式链接 查看获取MD5和SHA1值实际操作命令CMD语句: C:\Users\Administrator>cd .android C:\Users\Admin ...