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

Переопределение разрешено в C, но не на С++?

Почему этот код работает в C, но не в С++?

int i = 5;
int i; // but if I write int i = 5; again I get error in C also

int main(){

  // using i
}
4b9b3361

Ответ 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).

Также проверьте этот отличный пост по внешним переменным.

Ответ 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 */

С++ не поддерживает концепцию пробного определения: объявление внешних данных без спецификатора класса хранения всегда является определением.

Отсюда: Предварительные определения

Ответ 3

Чтобы лучше понять предварительное определение, пройдите this