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

标签 c coroutine setjmp

我试图在 c 语言中使用 生成类似 fibonacci 生成器序列(在 python 中使用 yield 关键字实现) >setjmp()longjmp() :

#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 位不正确的数字)

最佳答案

不幸的是你的程序有未定义的行为。

引用 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 中的

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

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

关于c - 使用 setjmp() 和 longjmp() 创建斐波那契生成器序列时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45399521/

相关文章:

android - 有没有办法重用 Job 实例?

kotlin - 如何从非暂停回调函数从LiveData构建器发出

c - 在多线程环境中捕获信号

c - 如何通过 stdin 提供输入来使以下条件失败

c++ - 有操作系统和没有操作系统的两个空 main{} 程序有什么区别?

kotlin - 在 Kotlin 中创建异步函数

c - 限制c中函数的执行时间

c - C中setjmp和longjmp的实际使用

c# - 计算闪存驱动器内容的校验和

c++ - 是否还需要 extern "C"才能将 Cpp 文件中使用的全局变量链接到 cfile 中定义的变量?