c/c++语言开发共享在C / C ++中取消初始化变量

这是一个理论问题而不是实际问题,但我想知道是否可以在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,因为这是一个非常好的值,…我只是希望它再次成为“我不知道任何事情“在初始化之前就已经开始了。”

(是的我知道: C中声明的,未初始化的变量会发生什么?它有值吗? )

    您可以使用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) 

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

    一个演示。

    更长的解释

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

    头文件定义了宏setjmp ,并声明了一个函数和一个类型,用于绕过正常的函数调用和返回规则。

    声明的类型是

    jmp_buf

    这是一种适合保存恢复调用环境所需信息的数组类型。 调用setjmp宏的环境包含足以调用longjmp函数的信息,以便将执行返回到正确的块并调用该块,如果它是递归调用的。 它不包括浮点状态标志,打开文件或抽象机器的任何其他组件的状态。

    这解释了应该发生的事情是,通过调用setjmplongjmp返回到保存在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:

    所有可访问的对象都具有值,并且抽象机器的所有其他组件都具有状态,截至调用longjmp函数时,除了自动存储持续时间的对象值是包含相应setjmp调用的函数的本地没有volatile限定类型并且在setjmp调用和longjmp调用之间已经更改的宏是不确定的

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

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

    你可以使用boost::optional来模拟这个:

     #include  int main() { boost::optional a; a = 7; std::cout << a.is_initialized() << std::endl; // true a.reset(); // "un-initialize" std::cout << a.is_initialized() << std::endl; // false } 

    我很好奇你为什么要那样做。 但是你试过以下:

     void some_fun() { int a; int b = a; // Hoping compiler does not discard this. a = 7; // do something a = b; } 

    另一种方法是:

     int a, olda; memcpy(&olda, &a, sizeof(a)); a = 7; //... memcpy(&a, &olda, sizeof(a)); // a is "uninitialized" 

    这避免了使用赋值的陷阱表示问题,依赖于char没有任何陷阱表示的事实。 它还比使用setjmp()longjmp()简单得多。

    需要了解更多c/c++开发分享在C / C ++中取消初始化变量,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!

      以上就是c/c++开发分享在C / C ++中取消初始化变量相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/979187.html

      (0)
      上一篇 2021年12月12日
      下一篇 2021年12月12日

      精彩推荐