这是一个理论问题而不是实际问题,但我想知道是否可以在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
函数的信息,以便将执行返回到正确的块并调用该块,如果它是递归调用的。 它不包括浮点状态标志,打开文件或抽象机器的任何其他组件的状态。
这解释了应该发生的事情是,通过调用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:
所有可访问的对象都具有值,并且抽象机器的所有其他组件都具有状态,截至调用
longjmp
函数时,除了自动存储持续时间的对象值是包含相应setjmp
调用的函数的本地值没有volatile限定类型并且在setjmp
调用和longjmp
调用之间已经更改的宏是不确定的 。
由于a
是本地的,不是volatile限定的,并且在setjmp
和longjmp
调用之间已被更改,因此它的值是不确定的, 即使它在调用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