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:声明浮 ...
随机推荐
- Distinct Subsequences leetcode java
题目: Given a string S and a string T, count the number of distinct subsequences of T in S. A subseque ...
- memcached安装和验证
1> libevent安装 官网down: http://www.monkey.org 我的网盘down:http://pan.baidu.com/s/1qW8syZi [root@luozh ...
- 学界 | Yann LeCun新作,中日韩文本分类到底要用哪种编码?
https://www.wxwenku.com/d/102093756 AI科技评论按:前几天,Yann LeCun与其学生 张翔在arXiv上发表了一篇新作「Which Encoding is th ...
- 教育单元测试mock框架优化之路(上)
转载:https://sq.163yun.com/blog/article/169561874192850944 众所周知,mock对于单元测试,尤其是基于spring容器的单元测试,是非常重要的.它 ...
- Python爬虫实战(三):爬网易新闻
代码: # _*_ coding:utf-8 _*_ import urllib2 import re #import sys #reload(sys) #sys.setdefaultencoding ...
- CSS 之 div中文字超出时自动换行
在开发中很容易遇到div中文字超出的问题,在此总结以下方法: 1. white-space :属性设置如何处理元素内的空白.这个属性声明建立布局过程中如何处理元素中的空白符.所有浏览器都支 ...
- 高级NUMA参数
Advanced NUMA Attributes You can use the advanced NUMA attributes to customize NUMA usage. Attribute ...
- C#中使用多款LevelDB.Net封装测试性能
一.使用http://www.nuget.org/packages/LevelDB.NET 测试 1.新建项目,并Nuget引入库: 2.写代码 using LevelDB; using System ...
- JAVA开发总结
1.Float取整 long warning; float fwarning = 0f; fwarning = total*0.34/100; warning = new Float(fwarning ...
- gradle 配置及设置本地仓库
安装Gradle 从官方网站下载安装包,解压到目录 设置环境变量 GRADLE_HOME=D:\gradle\gradle-3.4.1 PATH=;%GRADLE_HOME%\bin 设置本地仓库目录 ...