提问人:cmuse 提问时间:11/24/2010 最后编辑:Donald Duckcmuse 更新时间:7/10/2019 访问量:9030
为什么打印未初始化的变量时会看到奇怪的值?
Why do I see strange values when I print uninitialized variables?
问:
在下面的代码中,该变量没有初始值,并打印了此变量。
int var;
cout << var << endl;
输出 : 2514932
double var;
cout << var << endl;
输出 : 1.23769E-307
我不明白这些输出数字。谁能向我解释一下?
答:
当您这样做时:
int var;
您只声明了一个名为 的整数。您没有使用值对其进行初始化,因此无论在哪个位置,都将是垃圾数据。var
var
int var = 5;
将声明 var 并将其初始化为 5。
查看更多:http://en.wikipedia.org/wiki/Uninitialized_variable
在任何一种情况下,您都没有初始化,因此您会得到垃圾输出。var
你做过吗
const int var(5);
它将使用以下值进行初始化5
你得到的是编译器决定变量应该被解释为整数或双精度值的堆栈上的任何数据。每次程序运行时,它可能都是一样的,因为程序通常具有确定性。尽管在许多情况下,它最终会从程序的运行到运行中变得不相同。如果你稍微改变你的程序,或者让它在你得到该代码之前根据用户输入做出决定,你可能会也可能不会得到不同的数字。
基本上,您尚未初始化的变量的值是未指定的,并且可能绝对是任何值。那里有什么没有押韵或理由。使用未初始化的变量(从形式上讲)是未定义的行为,可能会导致各种奇怪的事情。
这样做通常是不好的做法。您希望程序以可预测的方式运行,而具有未初始化的变量是不可预测性的根源。请注意,它最强调的不是随机性的来源,而是不可预测性。如果你打开所有警告,大多数编译器都会抱怨这样的代码。
评论
简单地说,未初始化,读取未初始化的变量会导致未定义的行为。var
所以不要这样做。在你这样做的那一刻,你的程序不再保证做你说的任何事情。
从形式上讲,“读取”一个值意味着对它执行左值到右值的转换。§4.1 规定“......如果对象未初始化,则需要此转换的程序具有未定义的行为。
实际上,这只是意味着该值是垃圾(毕竟,很容易看到读取 ,例如,只是得到随机位),但我们不能得出这样的结论,否则您将定义未定义的行为。int
对于一个真实的例子,请考虑:
#include <iostream>
const char* test()
{
bool b; // uninitialized
switch (b) // undefined behavior!
{
case false:
return "false"; // garbage was zero (zero is false)
case true:
return "true"; // garbage was non-zero (non-zero is true)
default:
return "impossible"; // options are exhausted, this must be impossible...
}
}
int main()
{
std::cout << test() << std::endl;
}
天真地,人们会得出结论(通过评论中的推理)这不应该打印;但是对于未定义的行为,一切皆有可能。使用 编译它。"impossible"
g++ -02
评论
double
double
double
bool
"false"
"impossible"
false
true
当您声明 var 时,它会在内存中分配一个位置。但是,默认情况下,该内存不会设置为任何内容,因此您可以拾取之前存在的任何内容。这将是一些没有意义的垃圾值。
在 C++ 中,成员变量和局部变量都是如此。但是,在 Java 和 C# 等语言中,成员变量会自动初始化为 0(对于数字类型),对于布尔值,对于引用,则自动初始化为 null。这不会针对局部变量执行,并且(至少在 C# 编译器中)如果尝试获取未初始化变量的值,则生成将失败。
在 C++ 中,当您声明变量时,编译器会为其分配一个内存地址。就是这样,没有进行清理。这主要是因为 C++(和 C)在构建时考虑了性能。C++ 不会花时间初始化地址,除非您明确告诉它这样做。
你所看到的所谓垃圾 是最后一个使用它的变量留在该地址的任何东西。
其他语言将为您初始化数据。事实上,在初始化变量之前,C# 不允许您使用该变量。这些语言被设计为安全,从某种意义上说,它不会让你编写错误使用未初始化地址的代码,导致程序崩溃,或者更糟糕的是,损坏你的数据。
评论
-Wall
gcc -Wall source.c -o myexecutable