Почему внешняя ссылка не связана со статической переменной?
===========================================================

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

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

 

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

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

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

 .i1a { width: 336px; height: 280px; }
 @media(min-width: 768px) { .i1a { width: 728px; height: 90px; } }
 @media(min-width: 992px) { .i1a { width: 360px; height: 300px; } }
 @media(min-width: 1083px) { .i1a { width: 728px; height: 90px; } }

 (adsbygoogle = window.adsbygoogle || []).push({});

Для пуристов в аудитории: 'файл' = единица компиляции.

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

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

 

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

 .i2a { width: 336px; height: 280px; }
 @media(min-width: 768px) { .i2a { width: 728px; height: 90px; } }
 @media(min-width: 992px) { .i2a { width: 360px; height: 300px; } }
 @media(min-width: 1083px) { .i2a { width: 728px; height: 90px; } }

 (adsbygoogle = window.adsbygoogle || []).push({});

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

 

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

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

 

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

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

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