#define setjmp(env) /* 由具体实现定义 */
!subtitle:说明
将当前执行上下文保存到 jmp_buf 类型的变量 env 中,这个变量可在之后用于 longjmp 函数恢复当前执行上下文。
可以在以下位置调用 setjmp 保存执行上下:
整个表达式语句
setjmp(env);
if, switch, while, do-while, for 的整个控制表达式
switch (setjmp(env)) { /* ... */ }
一元运算符 ! 的操作数,运算结果为 if, switch, while, do-while, for 的整个控制表达式
while (!setjmp(env)) { /* ... */ }
关系运算符的第一个操作数,并且另一个操作数是常量表达式,关系运算的结果为 if, switch, while, do-while, for 的整个控制表达式
if (setjmp(env) > 10) { /* ... */ }
在其它上下文中调用 setjmp 是未定义行为。
调用 longjmp 函数时,程序会回到 setjmp 保存上下文的位置继续进行,setjmp 会返回 longjmp 的第二个参数。
除了 setjmp 所在函数的非 volatile 局部变量以外,所有可访问的对象、浮点状态标志以及所有其它组件的值都是调用 longjmp 函数时的值,而不是 setjmp 保存上下文时的值。
setjmp 所在函数的非 volatile 局部变量的值为 setjmp 保存上下文时的值,且调用 setjmp 后不可进行修改,否则该变量的值在调用 longjmp 函数返回后是不确定的。
如果需要在调用 setjmp 后修改所在函数的局部变量,则该局部变量应当声明为 volatile。
!subtitle:参数
env - 用于保存当前执行上下文
!subtitle:返回值
#include <stdio.h>
#include <setjmp.h>
#include <stdnoreturn.h>
// 保存上下文的变量
jmp_buf env;
void func(int status)
{
printf("调用 func(%d)\n", status);
longjmp(env, status); // 跳转,setjmp 返回 status
}
int main(void)
{
volatile int count = 0; // 这个变量在 setjmp 之后会被修改,因此声明为 volatile
if (setjmp(env) < 5) // 保存上下文,检查返回值
func(count++); // 修改了 count 的值
return 0;
}
运行结果:
调用 func(0)
调用 func(1)
调用 func(2)
调用 func(3)
调用 func(4)
调用 func(5)
C17 standard (ISO/IEC 9899:2018):
7.13.1.1 The setjmp macro (p: 191)
C11 standard (ISO/IEC 9899:2011):
7.13.1.1 The setjmp macro (p: 262-263)
C99 standard (ISO/IEC 9899:1999):
7.13.1.1 The setjmp macro (p: 243-244)
C89/C90 standard (ISO/IEC 9899:1990):
4.6.1 The setjmp macro