我有一个关于未初始化变量在C中如何工作的问题。如果我声明一个变量然后打印它,程序应该打印一个随机值,但我的程序几乎总是输出0。如果我试图声明第二个变量,程序总是输出16作为新赋值。
#include <stdio.h>
int main(){
int x,y,z,t;
printf("%d %d",x,y);
}
这个程序输出0和16,但是,如果我在声明变量之后但在打印变量之前添加以下代码行:y--;
,程序输出x=15和y=-1,这与我以前的值完全不同。为什么会发生这种情况?C如何处理未初始化的变量?
根据标准(草案N1570),以下内容适用:
6.2.4
对象的初始值是不确定的。
对此进行了进一步描述
6.7.9
如果没有显式初始化具有自动存储持续时间的对象,则其值为不确定的
;不确定的";表示
3.19.2
不确定值
未指定的值或陷阱表示
最后是
J.2未定义的行为
在以下情况下行为未定义:
。。。
具有自动存储持续时间的对象的值在不确定(6.2.4、6.7.9、6.8)。
总之:当读取未初始化的变量时,无法知道你得到了什么值,此外,它甚至不确定你的程序是否会继续执行,因为这可能是一个陷阱。
回答这个问题的一种方法是,当你读到;未初始化的变量开始时包含随机值";,在这种情况下,您在中看到的那些值0、16、15和-1是";"随机";。
现在,这是真的,它们肯定不是随机的,比如说,掷骰子是随机的。它们似乎保持不变,然后无缘无故地改变,比如当你改变程序的其他部分时。
但你显然无法预测它们。所以你显然不能使用它们,或者以任何方式依赖它们。它们可能真的是随机的。
为什么他们有他们所拥有的特定价值观?这几乎是不可能的。不管是什么原因,它们往往都不是很有趣。不管是什么原因,它们通常都不重要,因为在任何正常的程序中,你永远不会依赖那些未初始化的值。
这有点像在问,";我从厨房桌子上锯下三条腿。所有东西都掉到地板上摔碎了。除了一个盘子没有坏。为什么它没有坏?还有一个苹果,它滚进了客厅。我原以为它会滚下地下室的楼梯。为什么它滚进客厅"大多数时候,答案很简单:;一开始就不要把腿从桌子上锯下来">
问题的另一部分与以下事实有关:未初始化的变量y
一开始似乎包含值16,但当添加语句y--
时,值变为-1。怎么了?
答案是,我们谈论的是un初始化变量和un可预测行为。当你未能初始化一个变量,这意味着你的程序有不可预测的行为时,不会发生的事情是,某个预言家为你的变量选择了一个初始值,然后安排你的程序的其他一切都是可预测的。不,你的程序不可预测意味着你无法预测它!如果昨天这个不可预测的值似乎是16,那么你无法预测明天减去1会得到15。
(继续我愚蠢的比喻,如果你明天再看到厨房桌子上的腿,你不会想到你一定会再看到一个完整的盘子。如果你把腿按不同的顺序锯掉,希望桌子从不同的角度掉下来,像你预期的那样把苹果从地下室楼梯上拿下来,你可能也不会如果不起作用,则指向。)
如果你真的想知道发生了什么,部分答案是局部变量通常存储在堆栈上,它们一开始包含任何";"随机";位模式被留在堆栈上的那个位置,不管函数最后一次使用堆栈中的那个部分作为自己的变量。因此,任何在堆栈上移动的东西,导致未初始化的变量在堆栈帧中占据不同的位置,或者导致前一个函数在堆栈上留下不同的垃圾,都会导致未初始化变量开始时持有不同的";"随机";价值有关尝试使用未初始化的基于堆栈的变量时会发生什么的更多讨论,请参阅另一个答案。
另请参见xkcd 221。