Множественные определения не дают ошибок или предупреждений ни в gcc, ни в clang

#c #gcc #compilation #clang #warnings

#c #gcc #Сборник #clang #предупреждения

Вопрос:

Если бы я это сделал

 #include <stdio.h>
int a; //definition
int a; //definition
int a; //definition
int a; //definition
int a; //definition
int main() {
    return 0;
}
  

Например, я бы не получил никаких ошибок или предупреждений ни от gcc, ни от clang, несмотря на многократное определение переменной. Почему? Я думал, что мне разрешено объявлять переменную столько раз, сколько я хотел, но мог определить ее только один раз?

Ответ №1:

Это предварительное определение. То есть каждое объявление переменной области видимости файла без инициализатора рассматривается как объявление, а не как определение. Определение неявно генерируется в конце единицы преобразования с инициализатором, равным 0.

Из стандарта C (6.9.2 Определения внешних объектов)

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

Комментарии:

1. Это объясняет, почему он не генерирует ошибку, но предупреждение все равно может быть уместным. Это потому, что обычно используется несколько предварительных определений из разных заголовочных файлов?

2. @Barmar Я думаю, что у компилятора может быть опция, которая устанавливает предупреждение. Например, для нескольких объявлений функций некоторые компиляторы по умолчанию выдают предупреждение.

3. Я попробовал -Weverything на своем Mac, он не предупредил об этом.

4. @Barmar Похоже, что разработчики компиляторов не считают, что это требуется. 🙂

5. Очевидно, что, хотя это кажется очевидным, о чем нужно предупреждать, если нет веской причины не делать этого.