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:声明浮 ...
随机推荐
- 华为推送 简介 集成 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- mybatis xml mapper 文件中 if-else 写法
mybaits 中没有else要用chose when otherwise 代替 范例一 <!--批量插入用户--> <insert id="insertBusinessU ...
- MFC剪贴板通信
1.建立一个基于对话框的应用程序,界面如下: 2.对两个按钮进行消息响应: void CChipBoardOperateDlg::OnBnClickedBtnCopycb() { // TODO: 在 ...
- tail -f 然后grep,处理缓存的问题
学习了:http://www.quwenqing.com/read-134.html 对日志记录做多次grep过滤输出,格式如下: tail -f log | grep xxx | grep yyy ...
- (转)Unity3D研究院之将场景导出XML或JSON或二进制并且解析还原场景
自:http://www.xuanyusong.com/archives/1919 导出Unity场景的所有游戏对象信息,一种是XML一种是JSON.本篇文章我们把游戏场景中游戏对象的.旋转.缩放.平 ...
- Sublime 3156 LICENSE key
mac sublime3 3156 LICENSE 转自:http://blog.csdn.net/myboyliu2007/article/details/78748253 下载地址:https:/ ...
- 阿里云centos配置nginx和nodejs
今天新买了阿里云,想把网站跑起来,于是记录跑起来的过程 1.购买域名 2.购买解析 3.购买ecs主机 4.ssh登录主机 5.安装vsftpd 6.配置ftp用户.文件夹.权限 7.安装nginx/ ...
- Kafka单机环境的部署
前面说过Kafka集群环境的部署,现在主要说一下在本地测试中Kafka单机环境的部署,和前面一样首先保证zookeeper服务的正常运行,然后解压并释放kafka安装包,并放到指定位置: tar -x ...
- iOS开发技巧 - 使用UISegmentedControl来对信息进行分组
(Swift) import UIKit class ViewController: UIViewController { var segmentedControl:UISegmentedContro ...
- Direct hosting of SMB over TCP/IP
http://support.microsoft.com/kb/204279 System TipThis article applies to a different version of Wind ...