Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Внешние переменные — это переменные в области видимости файла. Они определяются вне конкретной функции и потенциально доступны для множества функций. Функции можно определить только на внешнем уровне, и, следовательно, они не могут быть вложенными. По умолчанию все ссылки на внешние переменные и функции с одинаковым именем являются ссылками на один и тот же объект, что означает, что они имеют внешнее связывание. (Чтобы переопределить такое поведение, можно использовать ключевое слово static
.)
Объявления переменных на внешнем уровне являются определениями переменных (определяющие объявления) или ссылками на переменные, определенные в другом месте (ссылающиеся объявления).
Внешнее объявление переменной, которое также инициализирует переменную (неявно или явно), является определяющим объявлением переменной. Определение на внешнем уровне может принимать различные формы.
Переменная, объявляемая с использованием описателя класса хранения
static
. Вы можете явно инициализировать переменнуюstatic
с использованием константного выражения, как описано в статье Инициализация. Если опустить инициализатор, переменная инициализируется значением 0 по умолчанию. Например, следующие два оператора считаются определениями переменнойk
.static int k = 16; static int k;
Переменная, которая явно инициализируется на внешнем уровне. Например,
int j = 3;
— это определение переменнойj
.
В объявлениях переменных на внешнем уровне (т. е. вне любых функций) можно либо использовать описатель класса хранения static
или extern
, либо полностью опустить его. Вы не можете использовать терминальные описатели storage-class-specifier
auto
и register
на внешнем уровне.
После определения переменной на внешнем уровне она становится видимой во всей оставшейся части записи преобразования. Переменная невидима до ее объявления в том же исходном файле. Кроме того, она будет невидима в других исходных файлах программы, пока объявление не сделает ее видимой, как описано ниже.
Ниже приводятся правила в отношении static
.
Переменные, объявленные вне всех блоков без ключевого слова
static
, всегда сохраняют свои значения в течение всего хода выполнения программы. Чтобы ограничить доступ переменных к определенной записи преобразования, необходимо использовать ключевое словоstatic
. Это позволяет применить к ним внутреннее связывание. Чтобы сделать их глобальными для всей программы, опустите явный класс хранения или укажите ключевое словоextern
(см. правила в следующем списке). Это позволяет применить к ним внешнее связывание. Внутренняя и внешняя компоновки также описаны в разделе Компоновка.Указать переменную на внешнем уровне можно только один раз в рамках программы. Можно указать другую переменную с тем же именем и описатель класса хранения
static
в другой записи преобразования. Так как каждое определениеstatic
является видимым только в пределах собственной записи преобразования, конфликт не произойдет. Это удобный способ скрыть имена идентификаторов, которые должны совместно использоваться функциями в одной единице трансляции, но должны быть невидимы для других таких единиц.Описатель класса хранения
static
также может применяться к функциям. Если функция объявлена какstatic
, ее имя невидимо вне файла, в котором она объявлена.
Ниже приведены правила использования extern
.
Описатель класса хранения
extern
объявляет ссылку на переменную, определенную в другом месте. С помощью объявленияextern
можно сделать определение в другом исходном файле видимым или сделать переменную видимой до ее определения в том же исходном файле. После объявления ссылки на переменную на внешнем уровне переменная становится видимой во всей остальной части единицы трансляции, в которой находится объявленная ссылка.Чтобы ссылка
extern
стала допустимой, необходимо объявить переменную, на которую она ссылается, один и только один раз на внешнем уровне. Это определение (без класса храненияextern
) может находиться в любой из единиц трансляции, составляющих программу.
Пример
В примере ниже показаны внешние объявления.
/******************************************************************
SOURCE FILE ONE
*******************************************************************/
#include <stdio.h>
extern int i; // Reference to i, defined below
extern void other ( void ); // Reference to other(), defined in second source file
void next( void ); // Function prototype
int main()
{
i++;
printf_s( "%d\n", i ); // i equals 4
next();
}
int i = 3; // Definition of i
void next( void )
{
i++;
printf_s( "%d\n", i ); // i equals 5
other();
}
/******************************************************************
SOURCE FILE TWO
*******************************************************************/
#include <stdio.h>
extern int i; // Reference to i in
// first source file
void other( void )
{
i++;
printf_s( "%d\n", i ); // i equals 6
}
Два исходных файла в этом примере содержат три внешних объявления i
. Только одно объявление является определяющим. Это объявление
int i = 3;
определяет глобальную переменную i
и инициализирует ее начальным значением 3. Ссылочное объявление i
вверху первого исходного файла, которое использует extern
, делает глобальную переменную видимой до объявления, которое ее определяет. Ссылающееся объявление i
во втором исходном файле также делает переменную видимой в этом исходном файле. Если определяющий экземпляр переменной не указан в записи преобразования, компилятор предполагает, что имеется ссылающееся объявление
extern int x;
и что определяющая ссылка
int x = 0;
отображается в другой записи преобразования программы.
Все три функции (main
, next
и other
) выполняют одну и ту же задачу: они расширяют переменную i
и отображают ее значение. Отображаются значения 4, 5 и 6.
Если бы переменная i
не была инициализирована, ей автоматически было бы присвоено значение 0. В этом случае были бы отображены значения 1, 2 и 3. Дополнительные сведения об инициализации переменных см. в разделе Инициализация.