使用 setjmp() 和 longjmp() 创建斐波那契生成器序列时出错

error when creating fibonacci generator sequence using setjmp() and longjmp()

我正在尝试使用 setjmp() 和 [=15] 在 c 语言中制作类似于 fibonacci 生成器序列(使用 python 中的 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 不正确(15 位数字不正确)

要解决此问题 error,您必须使用 static variableglobal variable。当程序 运行 时,一个 static 变量保留在内存中。当声明变量的函数调用结束时,普通或自动变量被销毁:

#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);
    }
}

很遗憾,您的程序有未定义的行为。

引用 ISO 9899:1999,7.13.2.1 longjmp 函数 ,第 2 段:

The longjmp function restores the environment saved by the most recent invocation of the setjmp macro in the same invocation of the program with the corresponding jmp_buf argument. If there has been no such invocation, or if the function containing the invocation of the setjmp macro has terminated execution208) in the interim, or if the invocation of the setjmp macro was within the scope of an identifier with variably modified type and execution has left that scope in the interim, the behavior is undefined.

[...]

208) For example, by executing a return statement or because another longjmp call has caused a transfer to a setjmp invocation in a function earlier in the set of nested calls.

(强调我的。)

你的

        longjmp(childTask, 1);
main 中的

语句试图将控制转移到 child 中的 setjmp 调用,但是对 child 的调用已经 returned(通过longjmp(mainTask, 1)).

这不容易解决。 C 不允许您同时拥有两个活动函数 运行。一旦从一个函数中 return(通过使用 returnlongjmp),您将无法重新输入该调用。