加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在C/C++中取消初始化变量

发布时间:2020-12-16 10:34:56 所属栏目:百科 来源:网络整理
导读:这是一个理论问题而不是实际问题,但我想知道是否有可能在C(或C)中取消初始化变量.所以我们假设我们有以下代码: void some_fun(){ int a; // -- Here a is an un-initialized variable,it's value is the value // found in the memory at the given locatio
这是一个理论问题而不是实际问题,但我想知道是否有可能在C(或C)中取消初始化变量.所以我们假设我们有以下代码:

void some_fun()
{
    int a; // <-- Here a is an un-initialized variable,it's value is the value
           // found in the memory at the given location.
    a = 7; // Now I have initialized it 

    // do something with a ... 

    // and here do something again with a that it 
    // will have the same state (ie: indeterministic) as before initialization  
}

(不,我不想在a中添加一个随机值,因为那也是初始化,也不是0,因为这是一个非常好的值,…我只是希望它再次出现在“我不知道”知道它的任何事情“在初始化之前就已经开始了.”

(是的我知道:What happens to a declared,uninitialized variable in C? Does it have a value?)

解决方法

您可以使用setjmp()和longjmp()来获取所需的行为,并重新安排代码.下面的代码将a初始化为1,以便print语句不会调用未定义的行为.

jmp_buf jb;

void some_func (void)
{
    int a = 1;

    if (setjmp(jb) == 0) {
        a = 7;

        // do something
        printf("a = %d (initialized)n",a);

        // use longjmp to make `a` not initialized
        longjmp(jb,1);
        // NOTREACHED
    } else {
        printf("a = %d (not initialized)n",a);
    }
}

longjmp()调用返回到保存的setjmp()上下文,移动到else情况意味着a尚未初始化.

当使用GCC进行优化编译时,上述函数输出:

a = 7 (initialized)
a = 1 (not initialized)

如果您希望在未启用优化的情况下执行此操作,请尝试将寄存器存储类添加到声明中.

A demo.

更长的解释

那么,为什么我认为setjmp()和longjmp()会起作用?这就是C.??11§7.13?1-2对它的评价:

The header <setjmp.h> defines the macro setjmp,and declares one function and
one type,for bypassing the normal function call and return discipline.

The type declared is

jmp_buf

which is an array type suitable for holding the information needed to restore a calling
environment. The environment of a call to the setjmp macro consists of information
sufficient for a call to the longjmp function to return execution to the correct block and
invocation of that block,were it called recursively.
It does not include the state of the
floating-point status flags,of open files,or of any other component of the abstract
machine.

这解释了应该发生的事情是,通过调用setjmp将longjmp返回到jmp_buf中保存的上下文,就像在longjmp调用之前运行的代码是递归函数调用一样,longjmp就像一个从递归调用返回setjmp.对我而言,这意味着自动变量将是“未初始化的”.

int a;

    // the following expression will be false if returning from `longjmp`
    if (setjmp(jb) == 0) {
        // this section of code can be treated like the `setjmp` call induced
        // a recursive call on this function that led to the execution of the
        // code in this body
        a = 7;
        //...
        // assuming not other code modified `jb`,the following call will
        // jump back to the `if` check above,but will behave like a recursive
        // function call had returned
        longjmp(jb,1);
    } else {
        // `a` expected to be uninitialized here
    }

但是,似乎有一个问题.从C.11§7.13.2?3:

All accessible objects have values,and all other components of the abstract machine
have state,as of the time the longjmp function was called,except that the values of
objects of automatic storage duration
that are local to the function containing the
invocation of the corresponding setjmp macro that do not have volatile-qualified type
and have been changed between the setjmp invocation and longjmp call are
indeterminate
.

由于a是本地的,不是volatile限定的,并且在setjmp和longjmp调用之间已经更改,因此它的值是不确定的,即使它在调用setjmp之前已正确初始化!

因此,在修改自动非易失性变量之后使用longjmp返回本地setjmp将始终导致在返回到setjmp之后使这些修改后的变量“未初始化”.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读