2

在一个小型嵌入式系统上工作时,我想尝试使用诸如 C 协程之类的东西,你发现这些协程是用 switch/case/macro 结构和 gcc 的标签作为值扩展来实现的。所以我想出了一些结构和函数以及一个模式,这样我就可以编写如下函数(只是一个测试/示例函数):

void fiber1(FiberContext *fiber)
{
    if (fiber->restore) goto fiber->restore; // initial jump if called for
stateA:
    printf("Fiber 1: A state\n");
    fiber->misc = &&stateB;
    fiber->restore = &&sleep;
    return;
stateB:
    printf("Fiber 1: A state\n");
    fiber->misc = &&stateA;
    fiber->restore = &&sleep;
    return;
sleep:
    fiberSleepTicks(fiber, 1000000);
    fiber->restore = fiber->misc ? fiber->misc : &&stateA;
    return;
}

但是 GCC 不喜欢原来的goto fiber->restorerestore是 FiberContext 的 void* 成员)。我的想法是,基本上,当我在外部结构中返回时,我会捕获要跳转到的标签,离开函数,然后返回并跳转到新标签。

我认为,我得出的结论是 GCC 不知道该怎么做,因为 && 运算符产生一个绝对跳转地址,而不是相对于当前函数堆栈的跳转地址。所以我不能安全地重用它,因为没有什么可说的,我不会用不同的堆栈深度调用这个函数。

所以我的问题基本上是双重的。我对为什么它不起作用/编译的理解正确吗?或者是别的什么,如果是这样,我在这个功能上做错了什么?我正在编译只是gcc -std=gnu99.

4

1 回答 1

1

尝试

goto *(fiber->restore);

http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html

此外,堆栈深度与函数代码地址无关——只有共享库重定位才有意义(上面的页面也解释了如何很好地做到这一点)。

于 2012-12-06T20:43:54.583 回答