Используя вновь объявленную переменную в инициализации (int x = x + 1)? - PullRequest
9 голосов
/ 22 марта 2012

Я просто наткнулся на поведение, которое меня удивило:

При написании:

int x = x+1;

в C / C ++ -программе (или даже более сложном выражении, включающем вновь созданную переменную x) мой gcc / g ++ компилируется без ошибок.В приведенном выше случае Х равен 1 впоследствии.Обратите внимание, что в предыдущей декларации нет переменной x в области видимости.

Так что я хотел бы знать, является ли это правильным поведением (и даже может быть полезным в некоторых ситуациях) или просто особенностью синтаксического анализатора с моим gccверсия или gcc в целом.

Кстати: следующее не работает:

int x++;

Ответы [ 8 ]

18 голосов
/ 22 марта 2012

С выражением:

int x = x + 1;

переменная x появляется в знаке =, поэтому вы можете использовать ее справа.Под словом «появляется» я подразумеваю, что переменная существует, но ей еще предстоит присвоить значение инициализатором.

Однако, если вы не инициализируете переменную со статической продолжительностью хранения (например, внефункция), это неопределенное поведение, так как x, который появляется, имеет произвольное значение.

C ++ 03 имеет это, чтобы сказать:

Точка объявления дляимя сразу после его полного декларатора (пункт 8) и до его инициализатора (если есть) ...

Пример:
int x = 12;
{ int x = x; }
Здесь второй хинициализируется своим собственным (неопределенным) значением.

Этот второй случай в значительной степени соответствует тому, что у вас есть в вашем вопросе.

8 голосов
/ 22 марта 2012

Это не так, это неопределенное поведение .

Вы используете неинициализированную переменную - x.Вы получаете 1 из чистой удачи, все может случиться.

К вашему сведению, в MSVS я получаю предупреждение:

Предупреждение 1 предупреждение C4700: используется неинициализированная локальная переменная 'i'

Кроме того, во время выполнения я получаю исключение, поэтому оно определенно не безопасно.

5 голосов
/ 22 марта 2012
int x = x + 1;

в основном

int x;
x = x + 1;

Вам только что повезло, что у вас есть 0 в x.

int x++;

однако невозможно в C ++ на уровне парсера! Предыдущий мог быть разобран, но был семантически неправильным. Второй даже не может быть разобран.

3 голосов
/ 22 марта 2012

Переменная определяется с "=", поэтому она действительна, и когда она определена глобально, она инициализируется как ноль, поэтому в этом случае это определенное поведение, в других переменная была деинициализирована как таковая до сих пор унифицирован (но увеличен с 1).
Заметьте, что это все еще не очень вменяемый или полезный код.

3 голосов
/ 22 марта 2012

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

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

1 голос
/ 05 июня 2014

Ваш код имеет две возможности:

  1. Если x - локальная переменная, у вас неопределенное поведение, так как вы используете значение объекта до начала его жизни.
  2. Если x имеет статическое или локальное время жизни потока, оно предварительно инициализируется равным нулю, и ваша статическая инициализация надежно установит его на 1. Это четко определено.

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

1 голос
/ 22 марта 2012

3.3.1 Точка объявления 1 Точка объявления имени находится сразу после его полного декларатора (пункт 8) и до его инициализатор (если есть), кроме случаев, указанных ниже. [Пример: int x = 12; { int x = x; } Здесь второй x инициализируется своим (неопределенное) значение. - конец примера]

Вышеуказанные состояния так и должны иметь неопределенное значение, вам повезло с 1.

0 голосов
/ 22 марта 2012

Это неопределенное поведение, и компилятор должен по крайней мере выдать предупреждение. Попробуйте скомпилировать, используя g++ -ansi .... Второй пример - просто синтаксическая ошибка.

...