Ответ 1
Предварительное определение разрешено в C, но не в С++.
Предварительное определение - это любое объявление внешних данных, которое не имеет спецификатора класса хранения и не имеет инициализатора.
C99 6.9.2/2
Объявление идентификатора для объекта с файловой областью без инициализатора и без спецификаций класса хранения или со спецификацией класса хранилища static, представляет собой предварительное определение. Если единица перевода содержит одно или несколько предварительных определений для идентификатор, а единица перевода не содержит внешнего определения для этого идентификатора, то поведение точно такое же, как если бы единица перевода содержала объявление области видимости этого идентификатор, с составным типом на конце блока перевода, с инициализатором равным 0.
Итак, int i
является предварительным определением. Компилятор C объединит все предварительные определения в одно определение i
.
В С++ ваш код плохо сформирован из-за Одно правило определения (раздел 3.2/1 ISO C++)
Никакая единица перевода не должна содержать более одного определения любой переменной, функции, типа класса, типа перечисления или шаблона.
//, но если я напишу
int i = 5;
снова, я получу ошибку в C также
Поскольку в этом случае это уже не является предварительным определением из-за инициализатора (5).
Просто для информации
J.5.11 Несколько внешних определений
Может быть более одного внешнего определения для идентификатора объекта с явным использованием ключевого слова extern или без него; если определения не совпадают или несколько инициализировано, поведение undefined (6.9.2).
Также проверьте этот отличный пост по внешним переменным.