使用setjmp()和longjmp()创建fibonacci生成器序列时出错

时间:2017-07-30 11:54:58

标签: c coroutine setjmp

我尝试使用fibonaccipythonc语言制作setjmp()生成器序列(使用longjmp()中的yield关键字实现)之类的内容:

#include <setjmp.h>
#include <stdio.h>

jmp_buf mainTask, childTask;
void child(void);
int main(void) {
    long i = 1;
    if (!setjmp(mainTask)) {
        printf("%ldth Parent\n", i++);
        child();
    }
    for (int j = 0;j < 9;j++) {
        printf("%ldth Parent\n", i++);
        if (!setjmp(mainTask)) {
            longjmp(childTask, 1);
        }
    }
}
void child (void) {
    int c = 0;
    long i = 1;
    long j = 1;
    long k = 0;
    for (;;) {
        printf("i is:%ld   j is:%ld\n", i, j);
        k = i + j;
        if(i <= j)
            i = k;
        else
            j = k;
        c++;
        printf("%dth fib number:%ld\n", c, k);
        if (!setjmp(childTask)) longjmp(mainTask, 1);
    }
}

它只适用于第一个数字。

*更新: 我预计2,3,5,8,13,...... 但它产生2,并且nexts不正确(15digits不正确的数字)

2 个答案:

答案 0 :(得分:2)

不幸的是,您的程序有不确定的行为。

引用ISO 9899:1999, 7.13.2.1 longjmp功能,第2段:

  

longjmp函数恢复最近调用的环境   setjmp宏在程序的相同调用中使用相应的   jmp_buf论点。如果没有这样的调用,或如果函数包含   调用setjmp宏已终止执行 208)在临时中,或者如果   setjmp宏的调用在变量的标识符范围内   修改后的类型和执行已将该范围留在过渡期,行为未定义

     

[...]

     

208)例如,通过执行return语句或,因为另一个longjmp调用导致了   转移到嵌套调用集早期函数中的setjmp调用

(强调我的。)

        longjmp(childTask, 1);
main中的

语句尝试将控制转移到setjmp中的child调用,但是child的调用已经返回(通过longjmp(mainTask, 1))。

这不容易解决。 C不允许您同时运行两个活动功能。从函数返回后(使用returnlongjmp),您无法重新进入该调用。

答案 1 :(得分:0)

要解决此问题error,您必须使用static variableglobal variable。程序运行时,static变量仍保留在内存中。当声明变量的函数调用结束时,将销毁normal或auto变量:

#include <setjmp.h>
#include <stdio.h>

jmp_buf mainTask, childTask;
void child(void);
int main(void) {
    long i = 1;
    if (!setjmp(mainTask)) {
        printf("%ldth Parent\n", i++);
        child();
    }
    for (int j = 0;j < 9;j++) {
        printf("%ldth Parent\n", i++);
        if (!setjmp(mainTask)) {
            longjmp(childTask, 1);
        }
    }
}
void child (void) {
    static int c = 0;
    static long i = 1;
    static long j = 1;

    long k = 0;
    for (;;) {
        printf("i is:%ld   j is:%ld\n", i, j);
        k = i + j;
        if(i <= j){
            i = k;
        }
        else{
            j = k;
        }
        c++;
        printf("%dth fib number:%ld\n", c, k);
        if (!setjmp(childTask)) longjmp(mainTask, 1);
    }
}