Каково поведение неинициализированной переменной, используемой в качестве собственного инициализатора? - PullRequest
0 голосов
/ 15 января 2019

Я только что заметил, что следующий код можно скомпилировать с помощью clang / gcc / clang ++ / g ++, используя стандарты c99, c11, c++11.

int main(void) {
    int i = i;
}

и даже с -Wall -Wextra ни один из компиляторов даже не сообщает о предупреждениях.

Изменив код на int i = i + 1; и с помощью -Wall, они могут сообщить:

why.c:2:13: warning: variable 'i' is uninitialized when used within its own initialization [-Wuninitialized]
    int i = i + 1;
        ~   ^
1 warning generated.

Мои вопросы:

  • Почему это даже разрешено компиляторами?
  • Что об этом говорят стандарты C / C ++? В частности, каково поведение этого? UB или зависит от реализации?

Ответы [ 3 ]

0 голосов
/ 15 января 2019

Я полагаю, что вы можете получить предупреждение в случае

int i = i + 1; 

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

int i = i;

также.

Почему это даже разрешено компиляторами?

В этом утверждении нет ничего неправильного. Смотрите соответствующие обсуждения:

для большего понимания.

Что об этом говорят стандарты C / C ++? В частности, каково поведение этого? UB или зависит от реализации?

Это неопределенное поведение, так как тип int может иметь представление ловушки, и вы никогда не брали адрес обсуждаемой переменной. Таким образом, технически вы столкнетесь с UB, как только попытаетесь использовать (неопределенное) значение, хранящееся в переменной i.

Вы должны включить предупреждения вашего компилятора. В gcc,

0 голосов
/ 15 января 2019

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

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

Если ваша реализация не имеет заполнение целыми числами, тогда значение просто неопределено и нет неопределенное поведение.

EDIT:

Более подробно, поведение все еще может быть неопределенным, если i никогда не получал его адрес в какой-то момент. Это подробно описано в разделе 6.3.2.1p2 стандарта C11:

Если lvalue обозначает объект автоматического хранения продолжительность, которая могла быть объявлена ​​с хранилищем реестра класс (никогда не был взят его адрес), и этот объект неинициализирован (не объявлено с инициализатором и без присвоения ему было выполнено до использования), поведение не определено.

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

0 голосов
/ 15 января 2019

Это предупреждение, оно не относится к стандарту.

Предупреждения эвристические с «оптимистичным» подходом. Предупреждение выдается только тогда, когда компилятор уверен , что это будет проблемой. В подобных случаях вам больше повезло с clang или новейшими версиями gcc, как указано в комментариях (см. Еще один мой связанный вопрос: , почему я не получаю предупреждение "used неинициализированный" от gcc в этом тривиальном пример ).

в любом случае, в первом случае:

int i = i;

ничего не делает, поскольку i==i уже. Возможно, что назначение полностью оптимизировано, поскольку оно бесполезно. С компиляторами, которые не «видят» самоинициализацию как проблему, вы можете сделать это без предупреждения:

int i = i;
printf("%d\n",i);

Принимая во внимание, что это вызывает предупреждение все в порядке:

int i;
printf("%d\n",i);

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

Во втором случае:

int i = i + 1;

Необходимо выполнить вычисление между неинициализированным значением и 1. Там происходит неопределенное поведение.

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