Почему внешняя ссылка не связана со статической переменной?
Почему extern int n
не компилируется при объявлении n (в другом файле) static int n
, но работает, когда объявляется int n
? (Оба эти объявления были в области файлов.)
В принципе, почему int n
в области файлов не совпадает с static int n
в той же области? Это только по отношению к внешнему виду? Если да, то как насчет extern я не хватает?
Ответы
Ответ 1
Целая цель static
состоит в том, чтобы объявить, что переменная закрыта для исходного файла, который объявлен в. Таким образом, он делает именно свою работу по предотвращению соединения с внешним.
Имейте в виду, что существует четыре варианта определения переменной области видимости файла:
-
int blah = 0;
- blah определен в этом файле и доступен из других файлов. Определения в других файлах являются дубликатами и приводят к ошибкам.
-
extern int blah;
- blah должен быть определен в другом месте и ссылается на этот файл.
-
int blah;
- Это моральный эквивалент FORTRAN COMMON
. Вы можете иметь любое количество из них в файлах, и все они разрешены компоновщиком для одного общего int
. (*)
-
static int blah;
(необязательно с инициализатором) - это статично. Он полностью закрыт для этого файла. Он не виден внешним файлам в других файлах, и у вас может быть много разных файлов, которые объявляют static TYPE blah;
, и все они разные.
Для пуристов в аудитории: 'файл' = единица компиляции.
Обратите внимание, что статические внутренние функции (не в области файлов) еще более жестко ограничены: если две функции объявляют static int bleh = 0;
даже в одном файле, они не связаны.
(*): для тех из вас, кто не знаком: в обычном шаблоне один блок компиляции должен определить глобальную переменную, а другие могут ссылаться на нее. Он "живет" в этой единице компиляции. В случае (3), выше, ни один файл (или все файлы) не определяет его. Если два файла говорят int blah = 0;
, компоновщик будет жаловаться на несколько определений. Если два файла говорят int blah;
, компоновщик весело создает единый глобальный int
и заставляет весь код ссылаться на него.
Ответ 2
В стандарте C существуют две области для переменных, объявленных вне функции. Переменная static
видна только внутри единицы компиляции (то есть файла), которая объявила его, а нестатические переменные видны во всей программе. Объявление extern
говорит, что местоположение переменной еще неизвестно, но будет сортироваться компоновщиком; он совместим с нестатическими переменными, но extern static
- просто сумасшедший разговор!
Конечно, на практике в наши дни есть и другие возможности. В частности, в настоящее время существуют уровни охвата между одним исходным файлом и целой программой; уровень одной общей библиотеки является полезной (настраивается с помощью таких механизмов, как атрибуты функции GCC). Но это всего лишь вариация темы нестатических переменных; static
сохраняет ту же интерпретацию, что и раньше.
Ответ 3
iv.c: 2: 1: ошибка: несколько классов хранения в спецификаторах объявлений
extern static int i;
^
Это то, что мы получаем от попытки статической переменной. Объявление extern static int i; - аналогично объявлению float int i;
Вы не можете иметь float и int в одной и той же декларации? Аналогично, вы не можете иметь extern и static в той же декларации.
Ответ 4
Согласно документации MSDN:
При изменении переменной ключевое слово static указывает, что переменная имеет статическую продолжительность (она выделяется при запуске программы и освобождается при завершении программы) и инициализирует ее до 0, если не указано другое значение. При изменении переменной или функции в области файла ключевое слово static указывает, что переменная или функция имеет внутреннюю привязку (ее имя не видно извне файла, в котором она объявлена).
http://msdn.microsoft.com/en-us/library/s1sb61xd(v=vs.80).aspx: июнь 2013 г.