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:声明浮 ...
随机推荐
- 关于APP接口设计 (转)
转自:http://blog.csdn.net/gebitan505/article/details/37924711 1.效率:接口访问速度 PHP建议使用YAF框架. 最好使用JSON格式数据,因 ...
- 【转】js面试题,明确自己的不足
https://blog.csdn.net/m0_37631322/article/details/85409716 -------------------- 2018年12月30日 21:05:43 ...
- Docker创建MySQL容器环境两部曲
1:下载MySQL镜像 需要执行以下命令,确保主机或者VM联网,从官网下载mysql的最新镜像(镜像版本以官网为主) docker pull mysql 下载成功后执行 docker image ...
- 【矩阵乘】【DP】【codevs 1305】Freda的道路
1305 Freda的道路 时间限制: 1 s 空间限制: 128000 KB 题目等级: 大师 Master 题目描写叙述 Description Freda要到Rainbow的城堡去玩了. 我们能 ...
- Android 原生 Android ActionBar Tab (滑动)导航
本文内容 环境 项目结构 演示一:ActionBar Tab 导航 演示二:ActionBar Tab 带滑动导航 本文演示 Tab 导航.第一个演示,是基本的 Tab 导航,第二个是带滑动的 Tab ...
- Hadoop学习笔记(一)——编译安装和配置
近期工作调动.打算补一下大数据处理的知识.可能会陆续涉及hadoop.mongodb.ddbs等. 首先Apache提供二进制的Hadoop版本号是32位的.在启动时总是有警告,所以想自己编译一遍.部 ...
- apache 反向代理的时候,通过域名访问是,出现跳转到ip或者无权访问的情况
解决方法很简单,在配置反向代理的时候加上一行: ProxyPreserveHost On 例如:ProxyPass / http://202.112.0.1/ProxyPassReverse / ht ...
- Spring整合Redis时报错:java.util.NoSuchElementException: Unable to validate object
我在Spring整合Redis时报错,我是犯了一个很低级的错误! 我设置了Redis的访问密码,在Spring的配置文件却没有配置密码这一项,配置上密码后,终于不报错了!
- Linux中10个有用的命令行补齐命令
本文转自GeekFan,感觉确实比较极客范啊,[TAB][TAB]补全都知道,但是你知道可以定制化补全吗? ---------------------------------------------- ...
- Word2007视频教程
超级好教程 http://v.youku.com/v_show/id_XMTAwOTgwNTIw.html 视频: oeasy教你玩转office系列之Word视频教程01 http://v.youk ...