По умолчанию глобальные переменные имеют внешнюю связь , что означает, что они могут использоваться другими исходными файлами (или «единицами перевода»). Если вы вместо этого объявите свои глобальные переменные с ключевым словом static
, у них будет внутренняя ссылка, то есть они не будут использоваться другими исходными файлами.
Для переменных с внешней связью вы не можете иметь несколько переменных с тем же именем, или компоновщик будет жаловаться. Однако вы можете иметь две переменные с тем же именем, хотя, по крайней мере, у одного есть внутренняя связь, и, конечно, вы не можете ссылаться на оба из них в том же исходном файле.
Объявление extern
просто говорит компилятору «вот имя некоторой переменной с внешней связью, определенной в другой единицы перевода», позволяющей ссылаться на эту переменную.
C++ - это точно то же самое, за исключением добавления пространств имен. Если глобальные переменные помещаются внутри пространства имен, они могут иметь одно и то же имя без ошибок компоновщика при условии, что они находятся в разных пространствах имен. Конечно, все ссылки на эти переменные затем должны либо ссылаться на полное имя namespace::var_name
, либо использовать объявление using
, чтобы установить локальный контекст пространства имен.
C++ также имеет анонимные пространства имен, которые полностью эквивалентны использованию ключевого слова static
для глобальных переменных в C: все переменные и функции, объявленные внутри анонимного пространства имен, имеют внутреннюю связь.
Таким образом, чтобы ответить на ваш первоначальный вопрос, вы правы - компиляция будет успешной, но связь потерпит неудачу из-за несколько определений переменной x
с внешним связыванием (в частности, от единиц перевода one.c
и two.c
).
От three.c
, нет возможности одновременно обращаться к обеим переменным x
. Вам нужно будет переименовать x
в один или оба модуля или переключиться на C++ и поместить хотя бы один x
в пространство имен.
Объявление переменной должно быть в заголовке, а заголовок должен использоваться в каждом файле, который ссылается на переменную, и должен использоваться в одном (одиночном, одиночном) файле, который фактически определяет переменную. Если вы попытаетесь связать код с двумя определениями одной глобальной переменной, вы находитесь за пределами стандартного поведения и в общих расширениях, задокументированных в стандарте (Приложение J). –
См. Также: http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c/ –