Подтвердить что ты не робот

Почему я вижу странные значения при печати неинициализированных переменных?

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

int var;
cout << var << endl;

выход: 2514932

double var;
cout << var << endl;

выход: 1.23769e-307

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

4b9b3361

Ответ 1

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

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


Формально "чтение" значения означает выполнение преобразования lvalue-to-rvalue на нем. И в §4.1 говорится: "... если объект неинициализирован, программа, которая требует этого преобразования, имеет поведение undefined".

Прагматически это означает, что значение является мусором (в конце концов, легко видеть, что чтение int, например, просто получает случайные биты), но мы не можем это сделать, или вы бы определили undefined.

Для реального примера рассмотрим:

#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;
}

Naïvely, можно было бы (по соображениям комментариев) заключить, что это никогда не должно печатать "impossible"; но с поведением undefined все возможно. Скомпилируйте его с помощью g++ -02.

Ответ 2

Когда вы выполните:

int var;

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

int var = 5;

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

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

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

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

Вы сделали

const int var(5);

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

Ответ 6

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

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