在setjmp.h中定义的C中的非本地跳转如何工作?

Tap*_*dra 3 c longjmp setjmp

C参考手册,附录B介绍两种功能setjmp,并longjmp为一些所谓的非本地的跳跃.除了setjmp保存状态信息和longjmp恢复的基本理解之外state,我还无法理解此功能的确切流程和用例.

那么,这个功能到底完成了什么,它在哪里有用?

Ker*_* SB 6

至于控制流程:setjmp返回两次,longjmp永不返回.当您setjmp第一次调用时,为了存储环境,它返回零,并且当您调用时longjmp,控制流将传递给返回setjmp参数中提供的值.

(注意,setjmp实际上不需要是函数;它可能是一个宏.但是它longjmp是一个函数.)

用例通常被称为"错误处理","不使用这些功能".

这是一个小控制流示例:

jmp_buf env;

void foo()
{
    longjmp(&env, 10);                      +---->----+
}                                           |         |
                                            |         |
int main()              (entry)---+         ^         V
{                                 |         |         |
    if(setjmp(&env) == 0)         | (= 0)   |         | (= 10)
    {                             |         ^         |
        foo();                    +---->----+         |
    }                                                 +---->----+
    else                                                        |
    {                                                           |
        return 0;                                               +--- (end)
    }
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 你不能传递0到longjmp.如果你这样做,1则返回setjmp.

  • 您不能从setjmp相应之前调用的函数返回longjmp.换句话说,longjmp只能在调用堆栈中调用上面 setjmp的内容.

  • (感谢@wildplasser :)你实际上无法存储结果setjmp.如果你想以几种不同的方式返回,你可以使用a switch,但:

    switch (setjmp(&env))
    {
    case 0:   // first call
    case 2:   // returned from longjmp(&env, 2)
    case 5:   // returned from longjmp(&env, 5)
    // etc.
    }
    
    Run Code Online (Sandbox Code Playgroud)