Область действия (scope rules) переменной – это правила, которые устанавливают, какие данные доступны из данного места программы. В языке С каждая функция – это отдельный блок программы. Попасть в тело функции нельзя иначе, как через вызов данной функции. С точки зрения области действия переменных различают три типа переменных: глобальные, локальные и формальные параметры. Правила области действия определяют, где каждая из них может применяться.
Локальные переменные – это переменные, объявленные внутри блока, в частности внутри функции. Язык С поддерживает простое правило: переменная может быть объявлена внутри любого блока программы. Локальная переменная доступна внутри блока, в котором она объявлена. Область действия локальной переменной – блок. Локальная переменная существует, пока выполняется блок, в котором она объявлена. При выходе из блока эта переменная (и ее значение) теряется.
Пример
#include <stdio.h>
Void f(void);
Void main(void)
{
Int i;
i=1;
F();
printf(“В функции main значение i равно %d\n”,i);
}
Void f(void)
{
Int i;
i=10;
printf(“В функции f() значение i равно %d\n”,i);
}
Пример показывает, что при вызове функции значение переменной i, объявленной в main() не изменилось.
Формальные параметры – это переменные, объявленные при описании функции как ее аргументы. Формальные параметры могут использоваться в теле функции, также как локальные переменные. Область действия формальных параметров – блок, являющийся телом функции.
Глобальные переменные – это переменные, объявленные вне какой-либо функции. В отличие от локальных переменных глобальные переменные могут быть использованы в любом месте программы, но перед их использованием они должны быть объявлены. Область действия глобальной переменной – вся программа.
Классы памяти
В языке С есть инструмент, позволяющий управлять ключевыми механизмами использования памяти и создавать гибкие и мощные программы. Этот инструмент – классы памяти. Каждая переменная принадлежит к одному из классов памяти. Эти классы описываются следующими ключевыми словами:
auto – автоматическая; extern – внешняя; static – статическая; register – регистровая.
Примеры:
Static int sum;
Register int plus;
Если ключевого слова перед спецификацией типа локальной переменной при ее объявлении нет, то по умолчанию она принадлежит классу auto. Автоматические переменные имеют локальную область действия. Они известны только внутри блока, в котором они определены. Автоматическая переменная создается (т.е. ей отводится место в памяти программы) при входе в блок функции. При выходе из блока автоматическая переменная пропадает, а область памяти, в которой находилась эта переменная, считается свободной и может использоваться для других целей. Автоматические переменные хранятся в оперативной памяти ЭВМ, точнее, в стеке. Регистровые (register) переменные хранятся в регистрах процессора. Доступ к переменным, хранящимся в регистровой памяти, значительно быстрее, чем к тем, которые хранятся в оперативной памяти ЭВМ. В остальном, регистровые переменные аналогичны автоматическим переменным.
Пример:
Register int quick;
Внешняя переменная (extern) относится к глобальным переменным. Она может быть объявлена как вне, так и внутри тела функции:
Void f(void)
{
extern int j; /* объявление внешней переменной внутри функции */
}
Для глобальных переменных выделяется место в разделе глобальных переменных и констант. Объявлений переменной как внешней может быть несколько, описание же переменной должно быть только одно. Следующий пример демонстрирует разные способы описания внешних переменных:
int var; /* описана внешняя переменная var */
Void main(void)
{
extern int var; /* объявлена та же внешняя переменная */
…
}
Func1()
{
extern int var1; /* объявлена внешняя переменная var1 */
/* переменная var также внешняя, хотя она не описана в этом блоке */
…
}
Func2()
{ /* переменная var внешняя */
/* переменная var1 невидима для этой функции в этом блоке */
}
int var1; /* описание внешней переменной */
Fun3()
{ /* для этой функции var1 внешняя */
int var; /* переменная var описана как локальная и не связана с глобальной переменной var */
/* по умолчанию эта переменная автоматическая */
}
Func4()
{ /* здесь переменная var является внешней глобальной переменной */
auto int var1; /* переменная var1 локальная автоматическая переменная */
}
При описании статических переменных перед описанием типа ставится ключевое слово static. Область действия локальной переменной - вся программа. Место в памяти под локальные переменные выделяется в начале работы программы в разделе глобальных и статических переменных. Однако область видимости локальных статических переменных такая же, как и у автоматических. Значение статической переменной сохраняется от одного вызова функции до другого. Локальные статические переменные инициализируются нулем, если не указан другой инициализатор.
При этом описание с инициализацией static int count = 10; локальной статической переменной count вызывает однократную инициализацию переменной count при выделении для нее памяти. При последующих вызовах функции, в которой описана эта переменная, инициализации не происходит. Это позволяет использовать такую переменную для счетчика вызова функций.
#include <stdio.h>
/* использование статической переменной */
void trystat(void); /* прототип функции */
Void main(void)
{
Int i;
for(i=1; i<=3; i++)
{
printf(“Call # %d\n”,i);
Trystat();
printf(“Call # %d\n”,i);
Trystat();
}
}
Void trystat(void)
{
int auto_l=1;
static int stat_l=1;
printf(“auto_l=%d stat_l=%d\n”,auto_l++, stat_l++);
}
Можно также описать глобальную (внешнюю) статическую переменную, т. е. описать переменную типа static вне любой функции. Отличие внешней переменной от внешней статической переменной состоит в области их действия. Обычно внешняя переменная может использоваться функциями в любом файле, в то время как внешняя статическая переменная только функциями того файла, где она описана, причем только после ее определения. Все глобальные переменные – и статические, и нестатические – инициализируются нулем, если не предусмотрено другой инициализации.
В следующей таблице приведены область действия и продолжительность существования переменных разных классов памяти:
Класс памяти | Ключевое слово | Время существования | Область действия |
Автоматический | auto | временно | блок |
Регистровый | register | временно | блок |
Статический локальный | static | постоянно | блок |
Статический глобальный | static | постоянно | файл |
Внешний | extern | постоянно | программа |