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

转载于:https://www.cnblogs.com/weiyinfu/p/9774260.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值