Почему не внешняя ссылка на статическую переменную? - PullRequest
54 голосов
/ 16 мая 2010

Почему extern int n не компилируется, когда n объявлено (в другом файле) static int n, но работает, когда объявлено int n? (Оба эти объявления были в области видимости файла.)

По сути, почему int n в области файла не совпадает с static int n в той же области? Это только по отношению к extern? Если да, то как насчет extern, который мне не хватает?

Ответы [ 4 ]

112 голосов
/ 16 мая 2010

Вся и вся цель static состоит в том, чтобы объявить, что переменная закрыта для исходного файла, который объявлен в . Таким образом, он делает именно свою работу по предотвращению соединения извне.

Имейте в виду, что существует четыре варианта определения переменной области файла:

  1. int blah = 0; - бла определяется в этом файле и доступна из других файлов. Определения в других файлах являются дубликатами и приведут к ошибкам.
  2. extern int blah; - blah должен быть определен в другом месте и на него есть ссылки из этого файла.
  3. int blah; - это моральный эквивалент Фортрана COMMON. Вы можете иметь любое количество таких файлов в файлах, и все они разрешаются компоновщиком в один общий int. (*)
  4. static int blah; (опционально с инициализатором) - это статично. Это полностью личное для этого файла. Он не виден внешним файлам в других файлах, и вы можете иметь много разных файлов, которые все объявляют static TYPE blah;, и все они отличаются .

Для пуристов в аудитории: 'file' = блок компиляции .

Обратите внимание, что статические внутренние функции (не в области видимости файла) еще более ограничены: если две функции объявляют static int bleh = 0; даже в одном и том же файле, они не связаны.

(*): для тех из вас, кто не знаком: в обычном шаблоне одна единица компиляции должна определять глобальную переменную, а другие могут ссылаться на нее. Он «живет» в этой сборочной единице. В случае (3) выше ни один файл (или все файлы) не определяет его. Если в двух файлах указано int blah = 0;, компоновщик будет жаловаться на несколько определений. Если два файла говорят int blah;, компоновщик весело создает один глобальный int и заставляет весь код обращаться к нему.

6 голосов
/ 16 мая 2010

В стандартном C есть две области действия для переменных, объявленных вне функции.Переменная static видна только внутри модуля компиляции (т. Е. Файла), который ее объявил, а нестатические переменные видны во всей программе.Объявление extern говорит, что местоположение переменной еще не известно, но будет отсортировано компоновщиком;он совместим с нестатическими переменными, но extern static - это просто сумасшедший разговор!

Конечно, на практике в наши дни существуют и другие видимости.В частности, теперь есть уровни видимости между уровнем одного исходного файла и всей программы;полезен уровень отдельной разделяемой библиотеки (устанавливаемый с помощью таких механизмов, как атрибуты функции GCC).Но это всего лишь вариация на тему нестатических переменных;static придерживается той же интерпретации, что и раньше.

1 голос
/ 17 декабря 2015

iv.c: 2: 1: ошибка: несколько классов хранения в спецификаторах объявления extern static int i; ^

Это то, что мы получаем при попытке выхода за пределы статической переменной. Объявление внешнего статического int i; - аналогично объявлению float int i; Вы не можете иметь float и int появляться в одной и той же декларации, верно? Точно так же вы не можете иметь extern и static в одном объявлении.

1 голос
/ 26 июня 2013

Согласно документации MSDN:

При изменении переменной ключевое слово static указывает, что переменная имеет статическую длительность (она выделяется при запуске программы, и освобождается при ее завершении), и инициализирует ее значением 0, если не указано другое значение. При изменении переменной или функции в области видимости ключевое слово static указывает, что переменная или функция имеет внутреннюю связь (ее имя не видно снаружи файла, в котором она объявлена).

http://msdn.microsoft.com/en-us/library/s1sb61xd(v=vs.80).aspx: Июнь 2013

...