• 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
    ",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虽好,可不要贪杯呀。

  • 相关阅读:
    数据库创建索引的缺点,和什么时候不该创建索引
    创建数据库,表,索引,删除索引,查看表中的索引和如何使用表中的索引
    java容器中 哪些是线程安全的
    java中集合类详解
    高并发 问题怎么解决
    数据库20个问题(关于事务、存储引擎、索引、悲观锁乐观锁)
    数据库事务(什么是事务)
    Application对象详解
    get和post 两种基本请求方式的区别
    BZOJ1003物流運輸 DP + SPFA
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/9774260.html
Copyright © 2020-2023  润新知