当我打印未初始化的变量时,为什么会看到奇怪的值?

时间:2010-11-23 19:20:27

标签: c++ variables c++-faq initialization

在以下代码中,变量没有初始值并打印此变量。

int var;
cout << var << endl;

输出:2514932

double var;
cout << var << endl;

输出:1.23769e-307

我不明白这些输出数字。任何人都可以向我解释一下吗?

6 个答案:

答案 0 :(得分:33)

简单地说,var未初始化,读取未初始化的变量会导致undefined behavior

所以不要这样做。你做的那一刻,你的程序不再保证做你说的任何事情。


正式地,“读取”值意味着对其执行左值到右值的转换。并且§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编译它。

答案 1 :(得分:3)

当你这样做时:

int var;

您只声明一个名为var的整数。您没有使用值初始化它,因此在var的任何位置都将是垃圾数据。

int var = 5;

声明var并将其初始化为5.

查看更多:http://en.wikipedia.org/wiki/Uninitialized_variable

答案 2 :(得分:2)

你得到的是在编译器决定将变量解释为整数或双精度的地方,堆栈上发生的任何数据。每次程序运行时,它可能都是相同的,因为程序通常具有确定性。虽然在很多情况下,从程序的运行到运行最终都不会是相同的。如果您稍微更改了程序,或者在获得该代码之前根据用户输入做出决定,您可能会或可能不会得到不同的数字。

基本上,未初始化的变量的值是未指定的,可能绝对是任何东西。什么都没有押韵或理由。

这样做通常是不好的做法。您希望程序以可预测的方式运行,并且具有未初始化的变量是不可预测性的来源。请注意,最重要的是它不是随机性的来源,只是不可预测性。如果你打开所有警告,大多数编译器都会抱怨这样的代码。

答案 3 :(得分:1)

在C ++中,当您声明一个变量时,编译器会为其分配一个内存地址。就是这样,没有完成清理工作。这主要是因为C ++(和C)在构建时考虑了性能。 C ++不会花时间初始化地址,除非你明确告诉它。

你看到的所谓的垃圾就是它使用它的最后一个变量留在那个地址的东西。

其他语言会为您初始化数据。事实上,在初始化之前,C#不会让你使用变量。这些语言被设计为安全,从某种意义上说,它不会让您编写错误地使用未初始化地址并使程序崩溃的代码,或者更糟糕的是,损坏您的数据。

答案 4 :(得分:0)

在任何一种情况下你都没有初始化var,所以你得到了垃圾输出。

你做完了

const int var(5);

它将使用值5

进行初始化

答案 5 :(得分:0)

当您声明 var 时,会在内存中为其分配一个位置。但是,默认情况下,该内存未设置为任何内容,因此您可以选择之前的内容。这将是一些毫无意义的垃圾价值。

在C ++中,对于成员变量和局部变量都是如此。但是,在Java和C#等语言中,您的成员变量会自动初始化为0表示数字类型,false表示布尔值,null表示引用。如果您尝试获取未初始化变量的值,则不会对局部变量执行此操作(至少在C#编译器中),您的构建将失败。