2

小さな組み込みシステムで作業していたので、switch/case/macro コンストラクトと gcc のラベルを値拡張として実装した C コルーチンのようなものを試してみたかったのです。そこで、次のような関数を記述できるように、いくつかの構造と関数、およびパターンを思いつきました (単なるテスト/サンプル関数)。

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->restore( restoreFiberContext の void* メンバーです)。私の考えでは、基本的に、外部構造に戻ったときにジャンプするラベルをキャプチャし、関数を離れてから、戻ってきて新しいラベルにジャンプするというものでした。

私が結論付けたのは、&& 演算子は現在の関数スタックに関連するものではなく、絶対ジャンプ アドレスを生成するため、GCC はそれを行う方法を知らないということです。したがって、スタックの深さが異なるとこの関数を呼び出さないということは何もないため、安全に再利用することはできません。

したがって、私の質問は基本的に 2 つあります。なぜそれが動作/コンパイルしないのか、私の理解は正しいですか? またはそれは何か他のものですか?もしそうなら、この機能の何が間違っていますか? だけでコンパイルしてい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 に答える