Когда вы объявляете свою переменную как в своем исходном сообщении, переменная получает внешнюю связь (с нашей без инициализатора - не имеет значения). Это означает, что переменные не являются независимыми. В обоих объявлениях имена относятся к одному и тому же объекту. Фактически, у вас есть несколько определений одного и того же объекта с внешней связью. Это является нарушением правил определения языка C, т. Е. Это то, что мы обычно называем ошибкой . Обратите внимание, что это ошибка в любом случае: с инициализатором или без него.
Причина, по которой ваш код, похоже, компилируется без инициализатора, является просто причудой вашего компилятора.
Я могу на самом деле догадаться, что такое заблуждение. Видите ли, язык C имеет интересную особенность (нет в C++, BTW) под названием Предварительные определения. Эта функция говорит, что если вы объявляете переменную, как это, без инициализаторе
int m_Test; /* no initializer */
вы создаете предварительное определение этой переменной. Вы можете объявить его таким же образом несколько раз в одной и той же единице трансляции
int m_Test;
int m_Test; /* OK in C */
int m_Test; /* OK in C */
(заметьте, опять-таки, что это было бы незаконным в C++). Если в какой-то момент вы обеспечиваете без предварительного определения для этой переменной
int m_Test = 0; /* non-tentative */
компилятор «сливаться» все эти предыдущие предварительные определения с этим.Но если вы не дают без предварительного определения, компилятор будет генерировать для вас неявно, и это будет эквивалентно
int m_Test = 0; /* implicit definition generated by the compiler */
Примечание, однако, что это применимо только в пределах одной и той же единице трансляции. Это означает, что как только вы написали что-то вроде этого
int m_Test; /* tentative */
это уже гарантирует, что эта переменная будет в конечном итоге быть не условно определено в этом переводе единицы (вами явно или неявно компилятором). Если вы сделаете то же самое в другой единицы перевода, эта переменная также будет определена там, что будет нарушать одни правила определения языка C.
Однако используемый вами компилятор должен относиться к правилам условного определения более дорогостоящим и позволяет что-то вроде «предварительных определений в нескольких единицах перевода». Вот почему вы не получаете ошибку в своем первом случае. Однако это всего лишь причуда вашего компилятора. Он по-прежнему является незаконным в C.
P.S. Как было отмечено в одной из связанных записей, это поведение является непереносимым «общим расширением» компиляторов C (даже упоминается в информационном разделе языкового стандарта). То есть некоторые компиляторы, как известно, допускают множественные объявления внешних объектов, если не более одного из них содержит инициализатор.
P.P.S. Конечно, если вы хотите, чтобы иметь indepedent переменные в разных единицах перевода, вы должны объявить их как static
, как уже отмечалось другими.
В ответах на этот вопрос можно найти подробные объяснения: http://stackoverflow.com/questions/1490693/tentative-definitions-in-c99-and-linking –
См. Также http://stackoverflow.com/questions/1787875/question-on-extern-specifier-in-c –