Область действия и область видимости

Область действия (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 постоянно программа