C和指针 第十六章 标准函数库 本地跳转setjmp.h

setjmp和longjmp提供一种类似goto语句的机制,但它的作用域不局限于同一个函数的作用域之内。这些函数可以用于深层次的嵌套函数调用链。

int setjmp(jmp_buf state);

必须声明一个jmp_buf变量,然后使用setjmp初始化,然后储存处理器状态信息,此时初始化的返回值为0。

void longjmp(jump_buf state, int value);

将保存的状态重新恢复,longjmp使执行流通过再次从setjmp函数返回,从而跳到顶层函数中。

#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>

jmp_buf restart;

void func1(void);
void func2(void);

int main(int argc, char **argv)
{
    if(setjmp(restart)){
        printf("program terminate \n");
        exit(EXIT_SUCCESS);
    }
    func1();
    printf("program terminate normally\n");

    return 0;
}

void func1(void)
{
    printf("into func one\n");
    func2();
    printf("out  func one\n");
}

void func2(void)
{
    printf("into func two\n");
    longjmp(restart, 1);
    printf("out  func two\n");
}

运行:

setjmp把处理器的状态信息保存到跳转缓冲区,如果变量设置为自动变量,除非没有被修改,否则,是未定义的行为。意思就是保存在内存中的变量,longjmp返回后,保持了longjmp时的值,而在cpu中的值将会退回到setjmp时的值。如下:

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

void change(int r, int s, int a, int v);
jmp_buf state;

int main()
{
    //r设置为寄存器变量
    register int r = 1;
    static   int s = 1;
    auto     int a = 1;
    volatile int v = 1;

    if(setjmp(state)){
        printf("r:%4d s:%4d a:%4d v:%4d\n", r, s, a, v);
        return 0;
    }
    r = s = a = v = 999;
    change(r, s, a ,v);
    return 1;
}

void change(int r, int s, int a, int v)
{
    printf("r:%4d s:%4d a:%4d v:%4d\n", r, s, a, v);
    //r寄存器变量,跳转时r是setjmp时的值
    longjmp(state, 1);
}

运行:

当setjmp调用函数返回后,可能无法再次调用longjmp。

 参考:https://en.wikipedia.org/wiki/Setjmp.h

posted @ 2016-09-15 19:51  xnuwu  阅读(253)  评论(0编辑  收藏  举报