c语言中setjmp与longjmp(3)

本文探讨了longjmp函数对不同类型的变量(如自动变量、寄存器变量等)的影响,并通过一个具体的C语言示例展示了在优化前后变量值的变化情况。文章强调了使用volatile属性来确保非局部跳转的可移植性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

longjmp对自动,寄存器,全局变量,静态变量,和易失变量(Volatile Variable)的影响

 

当longjmp返回到main函数时,这些变量的值是否能恢复到以前调用setjmp时的值(即滚回原先值),或者这些
变量的值保持为最新的值?不幸的是,对此问题的回答是“看情况”。大多数实现并不滚回这些自动变量和寄存器变量的值,而所有标准则说它们的值是不确定的。如果你有一个自动变量,而又不想使其值滚回,则可定义其为具有volatile属性。说明为全局和静态变量的值在执行longjmp时保持不变。

一下是APUE中的例子:
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

static void f1(int, int, int, int);
//static void f2(void);

static jmp_buf jmpbuffer;
static int globval;

int main(void)
{
     int autoval;
     register int regival;
     volatile int volaval;
     static int statval;

     globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5;

     if (setjmp(jmpbuffer) != 0) {
         printf("after longjmp:/n");
         printf("globval = %d, autoval = %d, regival = %d,"
             " volaval = %d, statval = %d/n",
             globval, autoval, regival, volaval, statval);
         exit(0);
     }

     /*
      * Change variables after setjmp, but before longjmp.
      */
     globval = 95; autoval = 96; regival = 97; volaval = 98;
     statval = 99;

     f1(autoval, regival, volaval, statval); /* never returns */
     exit(0);
}

static void f1(int i, int j, int k, int l)
{
    printf("in f1():/n");
    printf("globval = %d, autoval = %d, regival = %d,"
        " volaval = %d, statval = %d/n", globval, i, j, k, l);
       
    //f2();

    longjmp(jmpbuffer, 1);
}

static void f2(void)
{
    longjmp(jmpbuffer, 1);
}

如果以不带优化和带优化选项对此程序分别进行编译,然后运行它们,则得到不同的结果:


$ cc testjmp.c               compile without any optimization
    $ ./a.out
    in f1():
    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    after longjmp:
    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
   

$ cc -O testjmp.c            compile with full optimization
    $ ./a.out
    in f1():
    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    after longjmp:
    globval = 95, autoval = 2, regival = 3, volaval = 98, statval = 99

注意,易失变量(sum)不受优化的影响,在longjmp之后的值,是它在调用f1时的值。在我们所使用的setjmp(3)手册页上说明存放在存储器中的变量将具有longjmp时的值,而在CPU和浮点寄存器中的变量则恢复为调用setjmp时的值。这确实就是在运行以上程序时所观察到的值。不进行优化时,所有这三个变量都存放在存储器中(亦即对val的寄存器存储类被忽略)。而进行优化时,count和val都存放在寄存器中(即使count并末说明为register),volatile变量则仍存放在存储器中。通过这一例子要理解的是,如果要编写一个使用非局部跳转的可移植程序,则必须使用volatile属性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值