Как я могу получить gcc, чтобы предупредить меня о "int я = i;"

Простая программа:

int main()
{
    long i = i;

    return 0;
}

Компиляция в виде C не дает ошибок и предупреждений.

$ gcc -Wall -Wextra -pedantic 1.c

Компиляция в качестве C++ дает предупреждение:

$ c++ -Wall -Wextra -pedantic 1.c
1.c: In function ‘int main():
1.c:3:7: warning: ‘i is used uninitialized in this function [-Wuninitialized]
  long i = i;

В обоих случаях переменная я кажется 0, хотя в C++ она может быть неинициализирована. Я действительно сделал такую опечатку в одной из моих функций, и ее было довольно сложно найти. Что я могу сделать, чтобы этого избежать? Я бы ожидал хотя бы предупреждения. Более того, Clang не дает никаких предупреждений в любом случае (c или C++). Есть ли определенная часть стандарта, которая говорит что-нибудь об этом поведении?

Изменение: попробовав что-то похожее:

$ cat 1.c
int main(void)
{
    int k = k + 0;
    int i = i + 1;
    return 0;
}

Предупреждение (в C) генерируется только для "i".

$ gcc -Wall -Wextra 1.c
1.c: In function ‘main:
1.c:4:6: warning: ‘i is used uninitialized in this function [-Wuninitialized]
  int i = i + 1;

Ответы

Ответ 1

Для GCC-компиляции программ на C вам нужно добавить флаг компилятора -Winit-self. (Вам также нужны -Wall или -Wuninitialized, см. Ниже.) Для GCC, компилирующих C++ программы, этот флаг подразумевается -Wall но для C он должен явно -Wall; он также не является частью -Wextra.

Для Клана ситуация несколько интереснее. В фрагменте в OP Clang не производит никакой диагностики. Тем не менее, при немного другом фрагменте, приведенном в руководстве GCC ниже, предоставляется диагностика:

int f() {
  int i = i;
  return i;
}

Разница в том, что в приведенном выше фрагменте фактически используется (неинициализированное) значение i. По-видимому, в исходном коде Кланг обнаружил, что переменная была бесполезной и удалила ее как мертвый код перед применением диагностики.

В Clang диагностика запускается -Wuninitialized, которая активируется -Wall как в GCC.


Вот выдержка из руководства GCC:

-Winit-self (C, C++, Objective-C и Objective- C++)

Предупреждать о неинициализированных переменных, которые инициализируются сами по себе. Примечание. Эта опция может использоваться только с -Wuninitialized.

Например, GCC предупреждает о том, что i не инициализирован в следующем фрагменте, только когда -Winit-self ":

        int f()
          {
            int i = i;
            return i;
          }

Это предупреждение включено -Wall в C++.

Как показывает выдержка, -Wuninitialized также требуется. В C и C++ -Wall подразумевается -Wuninitialized. Однако обратите внимание, что многие неинициализированные виды использования не будут обнаружены, если не будет запрошен некоторый уровень оптимизации. Насколько я знаю, это не относится к -Winit-self. Его можно обнаружить без оптимизации.)


Раздражающе, когда вы снимаете вопрос в виде дубликата, исчезают ранее отмеченные дубликаты. Я не маркировал его, потому что ни один из дубликатов не ответил на вопрос в теле; Я также редактировал название.

Для справки, вот оригинальные дубликаты, которые могут представлять интерес:

Ответ 2

Это в основном:

int i;
i = i;

в которой i - неинициализированное значение.

Ответ 3

Комбинация -Wall -Winit-self похоже, добавляет эту диагностику:

$ gcc -Wall      -Winit-self t.c
t.c: In function ‘main:
t.c:3:10: warning: ‘i is used uninitialized in this function [-Wuninitialized]
     long i = i;
          ^