Из википедии http://en.wikipedia.org/wiki/External_variable:
Определение, объявление и ключевое слово extern
Чтобы понять, как внешние переменные связаны с ключевым словом extern, необходимо знать разницу между определением и объявлением переменной. Когда переменная определена, компилятор выделяет память для этой переменной и, возможно, также инициализирует ее содержимое некоторым значением. Когда переменная объявлена, компилятор требует, чтобы переменная была определена в другом месте. Объявление информирует компилятор о том, что переменная с таким именем и типом существует, но компилятору не нужно выделять для нее память, поскольку она размещена в другом месте.
Ключевое слово extern означает "объявлять без определения". Другими словами, это способ явного объявления переменной или принудительное объявление без определения. Также возможно явное определение переменной, то есть принудительное определение. Это делается путем присвоения значения инициализации переменной. Если нет ни ключевого слова extern, ни значения инициализации, оператор может быть либо объявлением, либо определением. Компилятор должен проанализировать модули программы и принять решение.
Переменная должна быть определена один раз в одном из модулей программы. Если нет определения или более одного, возникает ошибка, возможно, на этапе связывания. Переменная может объявляться много раз, если декларации согласуются друг с другом и с определением (что значительно облегчает заголовочные файлы). Он может быть объявлен во многих модулях, включая модуль, в котором он был определен, и даже много раз в одном и том же модуле. Но обычно бессмысленно объявлять это более одного раза в модуле.
Внешняя переменная также может быть объявлена внутри функции. В этом случае необходимо использовать ключевое слово extern, в противном случае компилятор будет считать его определением локальной переменной, которая имеет другую область видимости, время жизни и начальное значение. Это объявление будет видно только внутри функции, а не во всем модуле функции.
Ключевое слово extern, применяемое к прототипу функции, абсолютно ничего не делает (ключевое слово extern, применяемое к определению функции, конечно, бессмысленно). Прототип функции - это всегда объявление, а не определение. Кроме того, в ANSI C функция всегда является внешней, но некоторые расширения компилятора и более новые стандарты C позволяют определять функцию внутри функции.
Внешняя переменная должна быть определена ровно один раз за пределами любого
функция; это отводит хранилище для него. Переменная также должна быть
объявляется в каждой функции, которая хочет получить к ней доступ; это заявляет
тип переменной. Декларация может быть явным внешним
утверждение или может быть неявным из контекста. ... Вы должны отметить, что мы
когда мы ссылаемся на слова
к внешним переменным в этом разделе. Определение относится к месту
где переменная создается или назначается хранилище; декларация ссылается
в места, где указана природа переменной, но нет
выделяется.
- язык программирования C
Область действия, время жизни и статическое ключевое слово
Внешняя переменная может быть доступна для всех функций во всех модулях программы. Это глобальная переменная. Чтобы функция могла использовать переменную, объявление или определение внешней переменной должно находиться перед определением функции в исходном коде. Или внутри функции должно быть объявление переменной с ключевым словом extern.
Ключевое слово static (static и extern являются взаимоисключающими), применяемое к определению внешней переменной, меняет это немного: переменная может быть доступна только функциям в том же модуле, где она была определена. Но для функции в том же модуле возможно передать ссылку (указатель) переменной на другую функцию в другом модуле. В этом случае, даже если функция находится в другом модуле, она может читать и изменять содержимое переменной - она просто не может ссылаться на нее по имени.
Также можно использовать ключевое слово static в определении локальной переменной. Без ключевого слова static переменная автоматически выделяется при вызове функции и освобождается при выходе из функции (таким образом, имя «автоматическая переменная») Его значение не сохраняется между вызовами функций. При использовании ключевого слова static переменная выделяется при запуске программы и освобождается при ее завершении. Его значение не теряется между вызовами функций. Переменная все еще является локальной, поскольку к ней можно получить доступ только по имени внутри функции, которая ее определила. Но ссылка (указатель) на него может быть передана другой функции, что позволяет ей считывать и изменять содержимое переменной (опять же, не обращаясь к ней по имени).
Внешние переменные распределяются и инициализируются при запуске программы, а память освобождается только после завершения программы. Их время жизни такое же, как у программы.
Если инициализация не выполняется явно, внешние (статические или нет) и локальные статические переменные инициализируются равными нулю. Локальные автоматические переменные неинициализированы, то есть содержат значения «мусора».
Ключевое слово static, примененное к определению функции, предотвращает вызов функции по имени из-за пределов ее модуля (остается возможность передать указатель функции из модуля и использовать его для вызова функции).
Пример (язык программирования C)
Файл 1:
int GlobalVariable; // implicit definition
void SomeFunction(); // function prototype (declaration)
int main() {
GlobalVariable = 1;
SomeFunction();
return 0;
}
Файл 2:
extern int GlobalVariable; // explicit declaration
void SomeFunction() { // function header (definition)
++GlobalVariable;
}
В этом примере переменная GlobalVariable определяется в файле 1. Чтобы использовать ту же переменную в файле 2, она должна быть объявлена. Независимо от количества файлов глобальная переменная определяется только один раз, однако она должна быть объявлена в любом файле, кроме того, который содержит определение.
Если программа находится в нескольких исходных файлах, а переменная определена в file1 и используется в file2 и file3, то для подключения вхождений переменной необходимы внешние объявления в file2 и file3. Обычная практика - собирать внешние объявления переменных и функций в отдельный файл, исторически называемый заголовком, который включается #include в начале каждого исходного файла. Суффикс .h является стандартным для имен заголовков.