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语言中的随意跳转的更多相关文章

  1. C 语言中函数的跳转

    1.同一个函数内,可以使用goto语句: eg: void  text_1( void ) { char i=0; a : i++; printf ( " text_1 = %d \r\n& ...

  2. C语言中内存分配那些事儿

    C程序的内存结构 C语言的之所以复杂,首先它的内存模型功不可没.不像某些那样的高级语言只需要在使用对象的时候,用new创建.所有之后的事情,你不需要操心.对于C语言,所有与内存相关的东西,都需要熟悉, ...

  3. Java语言中的面向对象特性总结

    Java语言中的面向对象特性 (总结得不错) [课前思考]  1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类?  2. 面向对象编程的特性有哪三个?它们各自又有哪些特性?  3. 你知 ...

  4. 2.C语言中的关键字

    1.auto 修饰局部变量,编译器默认所有局部变量都是用auto来修饰的,所以在程序中很少见到. 2.static 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...

  5. C语言中关于对目录的操作

    原文地址:C语言中关于对目录的操作 目录的操作不论是在嵌入式产品还是应用软件编程都是必不可少的,不同的开发语言可能略有不同,笔者主要是讨论在Linux平台下对目录的一系列操作: 1.获取当前目录操作: ...

  6. c语言中函数调用的本质从汇编角度分析

    今天下午写篇博客吧,分析分析c语言中函数调用的本质,首先我们知道c语言中函数的本质就是一段代码,但是给这段代码起了一个名字,这个名字就是他的的这段代码的开始地址 这也是函数名的本质,其实也就是汇编中的 ...

  7. C语言中的转义字符

    转义字符 意义 ASCII码值(十进制) \a 响铃(BEL) 007 \b 退格(BS) ,将当前位置移到前一列 008 \f 换页(FF),将当前位置移到下页开头 012 \n 换行(LF) ,将 ...

  8. C语言中强制数据类型转换(转)

    原文地址不详 字符型变量的值实质上是一个8位的整数值,因此取值范围一般是-128-127,char型变量也可以加修饰符unsigned,则unsigned char 型变量的取值范围是0-255(有些 ...

  9. C语言中的关键字

    1.C语言中的关键字都有实际的意义. 2.C语言中的23个关键字如下: char:声明字符型变量. short:声明短整型变量. int:声明整型变量. long:声明长整型变量. float:声明浮 ...

随机推荐

  1. oracle的行级触发器使用

    行级触发器: 当触发器被触发时,要使用被插入.更新或删除的记录中的列值,有时要使用操作前.后列的值. :NEW 修饰符访问操作完成后列的值 :OLD 修饰符访问操作完成前列的值 例1: 建立一个触发器 ...

  2. Spring Boot集成持久化Quartz定时任务管理和界面展示

    本文是对之前的一篇文章Spring+SpringMVC+mybatis+Quartz整合代码部分做的一个修改和补充, 其中最大的变化就是后台框架变成了Spring Boot. 本工程所用到的技术或工具 ...

  3. [Canvas]游戏增加怪物爆炸效果,改善箭头形状

    请点此下载代码并用浏览器打开试玩. 图例: 代码: <!DOCTYPE html> <html lang="utf-8"> <meta http-eq ...

  4. (算法)Travel Information Center

    题目: Aps Island has many cities. In the summer, many travellers will come to the island and attend fe ...

  5. 《python源代码剖析》笔记 python中的List对象

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.PyListObject对象 --> 变长可变对象,可看作vector<Py ...

  6. 2014秋C++ 第9周项目 循环程序设计

    课程主页在http://blog.csdn.net/sxhelijian/article/details/39152703.课程资源在云学堂"贺老师课堂"同步展示,使用的帐号请到课 ...

  7. 第八周(1) Word信函与邮件

    第八周(1) Word信函与邮件 教学时间 2013-4-15 教学课时 2 教案序号 13 教学目标 1.学会使用word制作信封和标签2.理解邮件合并的概念和功能3.学会利用邮件合并批量制作文档 ...

  8. Java通过ScriptEngine 执行js脚本案例

    public static void main(String[] args) throws ScriptException, FileNotFoundException, NoSuchMethodEx ...

  9. 常用jQuery知识

    什么是jQuery jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML do ...

  10. SpringMVC学习笔记二:常用注解

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6831976.html  参考:http://www.cnblogs.com/leskang/p/5445698 ...