【问题标题】:Behaviour of Uninitialized Variables in CC 中未初始化变量的行为
【发布时间】:2021-09-07 05:20:59
【问题描述】:

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

【问题讨论】:

标签: c variables initialization global-variables uninitialized-constant


【解决方案1】:

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

6.2.4

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

这在

中有进一步的描述

6.7.9

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

“不确定”的定义说

3.19.2

不确定值

未指定的值或陷阱表示

最后

J.2 未定义的行为

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

...

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

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

【讨论】:

  • 附件 J 不规范,在这种情况下有不正确的信息。
【解决方案2】:

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

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

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

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

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

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

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

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

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

另见xkcd 221

【讨论】:

  • 关于“无论原因是什么,知道它们并不重要,因为你永远不会依赖这些价值观。”:这是从一个尝试和期待的人的角度写的编写具有已定义行为的程序。但是,恶意行为者可能对未初始化对象的行为非常感兴趣,因为它们可能有助于利用软件。人类会犯错误,因此优秀的工程师不能期望他们的程序总是有明确的行为,而必须了解程序如何行为不端。不应阻止人们了解这一点。
  • @EricPostpischil 我花了一段时间才做出回应,但是:我同意“人们不应该因为学习这种事情而气馁”,当回答者似乎如此气馁时,它常常让我烦恼,因为那些回答者(包括我自己)只对 C 有足够的了解以认为自己是“专家”,因为从前他们花了很多时间试图了解这些东西。我已经软化了这个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-22
  • 1970-01-01
  • 2016-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多