-1

我有一个关于未初始化变量如何在 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如何处理未初始化的变量?

4

2 回答 2

2

回答这个问题的一种方法是,当您阅读“未初始化的变量开始包含随机值”时,在这种情况下,您看到的那些值 0、16、15 和 -1“随机的”。

现在,这是真的,它们肯定不是随机的,比如掷骰子是随机的。它们似乎保持不变,然后无缘无故地改变,就像你改变程序的其他部分一样。

但你显然无法预测它们。所以你显然不能使用它们,或者以任何方式依赖它们。它们也可能是真正随机的。

为什么他们有他们所做的特定价值观?这几乎是不可能的。不管是什么原因,它们往往不是很有趣。不管是什么原因,知道它们通常并不重要,因为在任何理智的程序中,你永远不会依赖于那些未初始化的值。

这有点像在问:“我从厨房桌子上锯掉了三条腿。所有东西都掉到地上摔碎了。除了一个盘子没有碎。为什么它没有碎?还有一个苹果,它滚进了“ 大多数时候,答案很简单:“首先不要从桌子上看到腿!”

y您问题的另一部分与您的未初始化变量似乎开始包含值 16的事实有关,但是当您添加语句时y--,该值变为 -1。那是怎么回事?

答案是我们谈论的是初始化的变量和不可预测的行为。当您未能初始化变量时,这意味着您的程序具有不可预测的行为,不会发生的情况是某个地方的某个 oracle 为您的变量选择了一个初始值,然后安排有关您的程序的所有其他内容都是可预测的。不,你的程序不可预测意味着你无法预测它!如果无法预测的值昨天似乎是 16,那么您无法预测从中减去 1 会在明天得到 15。

(继续我愚蠢的类比,如果你明天再从厨房桌子上锯下腿,你不会期望你最终一定会再次得到一个完整的盘子。如果你以不同的顺序锯下腿,希望桌子以不同的角度落下并像您预期的那样将苹果引导到地下室楼梯,如果它不起作用,您可能不会失望。)

如果您真的想知道发生了什么,部分答案是局部变量通常存储在堆栈中,并且它们开始包含由上次使用的任何函数留在堆栈中该位置的任何“随机”位模式堆栈的一部分用于自己的变量。所以任何在堆栈上移动的东西,导致你的未初始化变量在堆栈帧中占据不同的位置,或者导致前一个函数在堆栈上留下不同的垃圾,都会导致你的未初始化变量开始持有不同的“随机”值。有关尝试使用未初始化的基于堆栈的变量时会发生什么的更多讨论,请参阅此其他答案。

另见xkcd 221

于 2021-06-23T16:21:25.150 回答
2

根据标准(草案 N1570),以下适用:

6.2.4

对象的初始值是不确定的。

这在中进一步描述

6.7.9

如果具有自动存储持续时间的对象未显式初始化,则其值是不确定的。

“不确定”的定义说

3.19.2

不确定值

未指定的值或陷阱表示

最后

J.2 未定义的行为

在以下情况下,行为未定义:

...

具有自动存储持续时间的对象的值在不确定时使用(6.2.4、6.7.9、6.8)。

综上所述:没有办法知道在读取未初始化的变量时你得到了什么值,而且甚至不确定你的程序是否会继续执行,因为它可能是一个陷阱。

于 2021-06-23T16:10:02.140 回答