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

Почему я не получаю "неиспользованное неинициализированное" предупреждение от gcc в этом тривиальном примере?

Еще раз глупая неинициализированная ошибка переменной в Как исправить эту ошибку сегментации в программе инвертирования последовательности?.

Итак, я собирался повторить "пожалуйста, используйте комментарий -Wall flags", но когда я протестировал код против предупреждений, я не обнаружил никаких предупреждений о моем большом удивлении.

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

#include <stdio.h>

int main()
{

  int i,len=12;

  /* printf("%d\n",i); */

  while(i!=len-1)
  {

    i++;
    len--;
  }

 return 0;
 }

при компиляции с использованием gcc 4.7.3 и 6.2.1 с использованием

gcc -Wall -Wextra -pedantic

Я не получаю никаких предупреждений, а i явно не инициализируется перед использованием в цикле while.

Теперь, если я раскомментирую оператор printf, я получаю:

warning: 'i' is used uninitialized in this function [-Wuninitialized]

Итак, почему предупреждение выдается при передаче i до printf, но не в тесте while?

(Это отличается от gcc неспособностью предупредить о неинициализированной переменной, потому что в моем случае нет ветвей)

(Звучит как ошибка, но это настолько тривиально, что я задаюсь вопросом, не пропал ли я что-то огромное.)

4b9b3361

Ответ 1

Трудно сказать, что это ошибка, потому что gcc смешивает код для оптимизации и для создания предупреждений, который даже задокументирован для этого конкретного предупреждения:

-Wuninitialized
Предупреждать, если автоматическая переменная используется без первоначальной инициализации или если переменная может быть сбита вызовом setjmp. [...]
Поскольку эти предупреждения зависят от оптимизации, точные переменные или элементы, для которых существуют предупреждения, зависят от точных параметров оптимизации и версии GCC.

(из документов GCC Параметры запроса или подавления предупреждений, акцент мой)

Вы нашли ИМХО очень глупый случай здесь. Попробуйте -O1, и вы получите неожиданное предупреждение:

warn.c: In function ‘main’:
warn.c:13:6: warning: ‘i’ may be used uninitialized in this function [-Wmaybe-uninitialized]
     i++;
      ^

Итак, gcc все еще пропускает первое неинициализированное использование, но находит второй! Попробуйте -O0 или -O2, и предупреждение снова исчезло...

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

warn.c:10:9: warning: variable 'i' is uninitialized when used here
      [-Wuninitialized]
  while(i!=len-1)
        ^
warn.c:6:8: note: initialize the variable 'i' to silence this warning
  int i,len=12;
       ^
        = 0
1 warning generated.