Почему этот код работает в C, но не в С++?
int i = 5;
int i; // but if I write int i = 5; again I get error in C also
int main(){
// using i
}
Почему этот код работает в C, но не в С++?
int i = 5;
int i; // but if I write int i = 5; again I get error in C also
int main(){
// using i
}
Предварительное определение разрешено в 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).
Также проверьте этот отличный пост по внешним переменным.
Tha называется предварительным определением. Это разрешено только в C.
Предварительное определение - любое внешнее декларация данных, которая не имеет хранилища спецификатор класса и инициализатор.предварительное определение становится полным если конец единица перевода достигнута, и нет определение появилось с инициализатор для идентификатора. В в этой ситуации резервы компилятора неинициализированное пространство для объекта определены.
Следующие утверждения показывают нормальные определения и предварительные определения.
int i1 = 10; /* definition, external linkage */
static int i2 = 20; /* definition, internal linkage */
extern int i3 = 30; /* definition, external linkage */
int i4; /* tentative definition, external linkage */
static int i5; /* tentative definition, internal linkage */
int i1; /* valid tentative definition */
int i2; /* not legal, linkage disagreement with previous */
int i3; /* valid tentative definition */
int i4; /* valid tentative definition */
int i5; /* not legal, linkage disagreement with previous */
С++ не поддерживает концепцию пробного определения: объявление внешних данных без спецификатора класса хранения всегда является определением.
Отсюда: Предварительные определения
Чтобы лучше понять предварительное определение, пройдите this