Переопределение разрешено в C, но не в C ++? - PullRequest
33 голосов
/ 17 марта 2011

Почему этот код работает в 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
}

Ответы [ 3 ]

50 голосов
/ 17 марта 2011

Предварительное определение разрешено в C, но не в C ++.

Предварительное определение - это любое внешнее объявление данных, которое не имеет спецификатора класса хранения и инициализатора.

C99 6.9.2 / 2

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

Так что int i является предварительным определением.Компилятор C объединит все предварительные определения в одно определение i.

В C ++ ваш код некорректен из-за One Definition Rule (Раздел 3.2 / 1 ISO C ++)

Никакая единица перевода не должна содержать более одного определения любой переменной , функции, типа класса, типа перечисления или шаблона.


// но если я напишу int i = 5; снова, я получаю ошибку в C также

Поскольку в этом случае он больше не остается предварительным определением из-заинициализатор (5).


Просто для информации

J.5.11 Несколько внешних определений

Может быть несколько внешних определенийдля идентификатора объекта, с или без явного использования ключевого слова extern;если определения не совпадают или инициализировано более одного, поведение не определено (6.9.2).

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

11 голосов
/ 17 марта 2011

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 */

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

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

2 голосов
/ 17 марта 2011

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

...