Присвоение указателя неинициализированной переменной меняет его значение? - PullRequest
3 голосов
/ 19 сентября 2011

Я играю с c ++ в VisualStudio2010

Пожалуйста, объясните, почему ЭТО происходит:

int a, b;
int *p, *q;
cout << a << " " << b;

выводит «0 0».Ну понятно, неинициализированное целое число должно быть 0;но

int a, b;
int *p, *q;
p = &a;
cout << a << " " << b;

вывод "1792816880 0"

Так что, если я назначу указатель на неинициализированную переменную, он изменит значение по умолчанию.Почему?

Правка уточнение: вопрос был не о значении неинициализированной переменной

int a; int *p;
cout << a; // would be 0, because it's loacal variable
p = &a;
cout << a; //not 0;

Как получить указатель a может изменить его значение?когда мы инициализируем переменную, мы выделяем пространство, некоторые биты, они могут быть чем угодно, но "p = & a" действительно изменяет биты в этом пространстве?

Ответы [ 7 ]

6 голосов
/ 19 сентября 2011

Ну понятно, неинициализированное целое число должно быть 0

номер

Это не гарантируется, это зависит от класса хранилища. Если ваша int является локальной переменной, она имеет автоматическое хранилище и не должна быть 0.

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

Что касается неопределенного поведения,

C ++ Стандартный раздел 1.3.24 гласит:

Допустимое неопределенное поведение варьируется от полного игнорирования ситуации с непредсказуемыми результатами до поведения во время перевода или выполнения программы задокументированным образом, характерным для среды (с выдачей или без выдачи диагностического сообщения), до прекращения перевода или выполнения ( с выдачей диагностического сообщения).

EDIT:
Учитывая вышеизложенное, что это неопределенное поведение и не следует писать код, основанный на таком поведении, на самом деле даже не следует думать о написании такого кода. Я считаю неуместным и непродуктивным копаться в реализации всех этих компиляторов, чтобы искать объяснение, почему он работает таким образом.

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

3 голосов
/ 19 сентября 2011

Это "неопределенное поведение" в C ++.

Когда вы не инициализируете переменную в C ++, она не всегда равна нулю.Это просто случайно.Память распределяется, и значение мусора, которое ранее находилось в этом месте памяти, будет выводиться до тех пор, пока оно не будет инициализировано.

2 голосов
/ 19 сентября 2011

Это неопределенное поведение, но вот некоторые предположения относительно того, что может происходить:

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

Во втором примере кода адрес берется так, что переменная должна находиться в памяти (в стеке), чтобы онаможет иметь адрес.Просто бывает, что в существующих данных был какой-то случайный мусор.

2 голосов
/ 19 сентября 2011

Значение неинициализированного значения не определено.Там нет значения по умолчанию.Может отображаться любое значение.

Любая, казалось бы, не связанная операция, которую вы выполняете, может изменить базовое значение мусора, которое программа даст вам в ответ на ваш запрос неопределенного значения.

Суть в том, не спекулируйте о том, что должно произойти неопределенное поведение.Это просто не определено - не пишите код с неопределенным поведением.

1 голос
/ 19 сентября 2011

У вас есть куча переменных, которые никогда не записываются. Компилятор может решить не выделять память для таких переменных. Это может показаться грубым, но это разумно: современные компиляторы распределяют хранилище переменных на детальном уровне, и некоторые переменные могут не использоваться в некоторых ветвях. Зачем беспокоиться о выделении памяти, когда она не нужна?

Теперь, что произойдет, если вы читаете из «переменной», которая не была выделена из памяти, потому что вы никогда не писали в нее? Вы получите некоторые случайные данные, вполне возможно, другую переменную. Или segfault - неопределенное поведение бывает во многих формах.

Теперь возьмем ваш второй пример: здесь вы делаете запись в одну переменную, p. Поскольку a не требовал выделения памяти (без записи), он вполне может иметь псевдоним p. И значение p, переосмысленное как int, вполне может быть 1792816880.

0 голосов
/ 19 сентября 2011

Неинициализированные локальные целые числа не гарантируются равными 0 в C ++.Они "мусор", следовательно, они могут иметь любое значение, включая 0.

0 голосов
/ 19 сентября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...