Почему при печати неинициализированных переменных появляются странные значения? - PullRequest
13 голосов
/ 23 ноября 2010

В следующем коде переменная не имеет начального значения и напечатала эту переменную.

int var;
cout << var << endl;

вывод: 2514932

double var;
cout << var << endl;

вывод: 1.23769e-307

Я не понимаю эти выходные цифры.Кто-нибудь может мне это объяснить?

Ответы [ 6 ]

34 голосов
/ 23 ноября 2010

Проще говоря, var не инициализируется, и чтение неинициализированной переменной приводит к неопределенному поведению .

Так что не делайте этого.В тот момент, когда вы это делаете, вашей программе больше не гарантируется выполнение того, что вы говорите.


Формально «чтение» значения означает выполнение преобразования lvalue в rvalue.И §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.

4 голосов
/ 23 ноября 2010

Когда вы делаете:

int var;

Вы объявляете только целое число с именем var. Вы не инициализируете его значением, поэтому в любом месте, где находится var, будут данные мусора.

int var = 5;

Объявляет var и инициализирует его до 5.

Подробнее: http://en.wikipedia.org/wiki/Uninitialized_variable

3 голосов
/ 23 ноября 2010

То, что вы получаете, это то, какие данные оказались в стеке в том месте, где компилятор решил, что переменная должна интерпретироваться как целое или двойное число.Вероятно, она будет одинаковой при каждом запуске вашей программы, потому что программы обычно ведут себя детерминистически.Хотя есть также много случаев, в которых это не будет одинаковым при запуске вашей программы.Если вы изменяете свою программу малейшим образом или она принимает решения на основе пользовательского ввода, прежде чем вы получите этот код, вы можете получить или не получить другие числа.

В основном значение переменной, которую вы не инициализировалине определено и может быть абсолютно любым.Там нет рифмы или причины того, что там.Использование неинициализированной переменной является (формально говоря) неопределенным поведением и может привести к всевозможным странным вещам.

Это обычно является плохой практикой.Вам нужны программы, которые ведут себя предсказуемо, а наличие неинициализированных переменных является источником непредсказуемости.Обратите внимание, что это наиболее определенно не источник случайности, просто непредсказуемость.Большинство компиляторов будут жаловаться на такой код, если вы включите все предупреждения.

2 голосов
/ 23 ноября 2010

В C ++, когда вы объявляете переменную, компилятор присваивает ей адрес памяти.И это все, очистка не производится.Это в основном потому, что C ++ (и C) создаются с учетом производительности.C ++ не тратит время на инициализацию адреса, если вы явно не скажете это сделать.

И так называемый мусор, который вы видите, это то, что он оставил по этому адресу последней переменной, которая его использовала.

Другие языки будут инициализировать данные для вас.Фактически, C # не позволит вам использовать переменную, пока вы не инициализируете ее.Эти языки спроектированы таким образом, чтобы быть безопасными , в том смысле, что они не позволят вам написать код, который по ошибке использует неинициализированный адрес и приведет к сбою вашей программы или, что еще хуже, повредит ваши данные.

1 голос
/ 23 ноября 2010

Когда вы объявляете var , ему назначается место в памяти.Однако эта память по умолчанию ничего не настроена, поэтому вы выбираете все, что было раньше.Это будет какое-то мусорное значение, которое не имеет смысла.

В C ++ это верно как для переменных-членов, так и для локальных переменных.Однако в таких языках, как Java и C #, переменные-члены автоматически инициализируются в 0 для числовых типов, false для логических значений и null для ссылок.Это не сделано для локальных переменных, и (по крайней мере, в компиляторе C #) ваша сборка завершится неудачно, если вы попытаетесь принять значение неинициализированной переменной.

1 голос
/ 23 ноября 2010

вы не инициализировали var в любом случае, поэтому вы получаете вывод мусора.

если бы вы сделали

const int var(5);

будет инициализировано значением 5

...