c - C 中未初始化变量的行为
问题描述
我有一个关于未初始化变量如何在 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如何处理未初始化的变量?
解决方案
回答这个问题的一种方法是,当您阅读“未初始化的变量开始包含随机值”时,在这种情况下,您看到的那些值 0、16、15 和 -1是“随机的”。
现在,这是真的,它们肯定不是随机的,比如掷骰子是随机的。它们似乎保持不变,然后无缘无故地改变,就像你改变程序的其他部分一样。
但你显然无法预测它们。所以你显然不能使用它们,或者以任何方式依赖它们。它们也可能是真正随机的。
为什么他们有他们所做的特定价值观?这几乎是不可能的。不管是什么原因,它们往往不是很有趣。不管是什么原因,知道它们通常并不重要,因为在任何理智的程序中,你永远不会依赖于那些未初始化的值。
这有点像在问:“我从厨房桌子上锯掉了三条腿。所有东西都掉到地上摔碎了。除了一个盘子没有碎。为什么它没有碎?还有一个苹果,它滚进了“ 大多数时候,答案很简单:“首先不要从桌子上看到腿!”
y
您问题的另一部分与您的未初始化变量似乎开始包含值 16的事实有关,但是当您添加语句时y--
,该值变为 -1。那是怎么回事?
答案是我们谈论的是未初始化的变量和不可预测的行为。当您未能初始化变量时,这意味着您的程序具有不可预测的行为,不会发生的情况是某个地方的某个 oracle 为您的变量选择了一个初始值,然后安排有关您的程序的所有其他内容都是可预测的。不,你的程序不可预测意味着你无法预测它!如果无法预测的值昨天似乎是 16,那么您无法预测从中减去 1 会在明天得到 15。
(继续我愚蠢的类比,如果你明天再从厨房桌子上锯下腿,你不会期望你最终一定会再次得到一个完整的盘子。如果你以不同的顺序锯下腿,希望桌子以不同的角度落下并像您预期的那样将苹果引导到地下室楼梯,如果它不起作用,您可能不会太失望。)
如果您真的想知道发生了什么,部分答案是局部变量通常存储在堆栈中,并且它们开始包含由上次使用的任何函数留在堆栈中该位置的任何“随机”位模式堆栈的一部分用于自己的变量。所以任何在堆栈上移动的东西,导致你的未初始化变量在堆栈帧中占据不同的位置,或者导致前一个函数在堆栈上留下不同的垃圾,都会导致你的未初始化变量开始持有不同的“随机”值。有关尝试使用未初始化的基于堆栈的变量时会发生什么的更多讨论,请参阅此其他答案。
另见xkcd 221。
推荐阅读
- elasticsearch - ElasticSearch 仅检索与单个文档中的术语匹配的列表元素
- ruby-on-rails - 如何让 has_and_belongs_to_many 进行批量插入?
- scala - 带有时间戳字段的 Elasticsearch 和 Spark 写入错误
- java - 运行测试时如何让maven找到本地jar
- c++ - libtins Sniffer undefined
- css - 当放入 sap.m.Dialog 控件时,如何使 sap.m.TextArea 控件变得响应?
- lit-element - 如何获取 LitElement 或 LitHtml 以从字符串呈现模板
- git - git.ignore 不适用于特定的 Unity Skybox 材质
- python - Pip 不会让我下载 Python 中的任何库
- python - 由于网站上的“显示更多”选项卡,熊猫没有从网站上读取所有表格