Классы памяти и области видимости переменных

Классы памяти

Класс памяти определяет «время жизни» объекта. Под объектом понимается идентификатор переменной, функция либо указатель функции. Кроме этого, класс памяти в совокупности с местоположением переменной в программе, определяет область видимости переменной.

Различают два вида объектов: глобальные и локальные.

Объекты с глобальным временем жизни существуют и имеют значение на протяжении всего времени исполнения программы.

Все функции и их указатели – глобальные объекты. Локальные объекты «захватывают» новую область памяти всякий раз, когда управление передается блоку, в котором они описаны.

Если переменная описана вне всяких блоков, то она считается глобальной. Это описание на так называемом внешнем уровне.

Блок- это описание функции, составная команда, либо часть программы, заключенная в фигурные скобки

{

это блок

}

Блоки могут быть вложенными:

{

{

это вложенный блок

}

}

Переменные, описанные внутри некоторого блока, являются локальными. При каждом входе в блок им выделяется новая область памяти, а при выходе из блока память освобождается и значение переменной, следовательно, теряется. Локальные объекты видны с момента их описания до конца блока.

Если при выходе из блока нужно сохранить значение переменной, то ее следует описать как статическую в данном блоке, например:

{

static int a;

...

}

Теперь при выходе из блока переменная а будет сохранять в памяти свое место и значение и будет «видна» только в этом блоке, а также в блоках вложенных в него.

Глобальные объекты видны с момента их описания до конца файла всем функциям (блокам).

Если имя локального объекта (переменной) совпадает с именем глобального объекта, то локальный объект маскирует глобальный в этом блоке.

Область действия меток - функция, в которой метка используется.

Пример 9.1: Область видимости переменных.

#include <stdio. h>

int k = 1; /* k = 1 */

void main(void)

{

printf(“k = %d \n”, k); // Результат: k = 1

{

//1-й вложенный блок

int k = 2, m = 5;

printf(“ k = %d \t m = %d \n”, k, m); // Результат: k =2, m = 5

{

//2-й вложенный блок

int k=0;

printf(“ k = %d \t m = %d \n”, k, m); // Результат: k=0, m=5

}

printf(“ k = %d \n”, k); // Результат: k=2

}

printf(“ k = %d \n”, k); // Результат:k=1

}

В приведенной программе четыре уровня видимости:

1) внешний уровень;

2) тело функции main();

3) 1-й вложенный блок;

4) 2-й вложенный блок

Внешний уровень – уровень файла. Объект внешнего уровня виден “всем в файле”. Время его жизни – глобальное. На локальном уровне внешний объект может быть переопределен.

Описатели классов памяти

Различают два класса объектов: глобальные и локальные, но используют четыре описателя классов: extern, static, auto и register. Назначение и применение их приведено в табл. 9.1

Таблица 9.1

Классы памяти

Класс памяти Ключевое слово Время действия Область действия
1. Автоматический auto временно локальная
2. Регистровый register временно локальная
3. Статический static постоянно локальная
4. Внешний extern постоянно глобальная (все файлы)
5.Внешний статический static постоянно глобальная (один файл)

Классы 1, 2 и 3 описываются внутри функций; Классы 4 и 5 описываются вне функций.

По умолчанию (без спецификаторов класса памяти) переменные, описанные внутри функции, являются автоматическими. Переменные, описанные вне функций по умолчанию - глобальные.

Класс памяти extern указывает, что глобальная переменная описана где-то в другом месте (в этом или другом файле). Таким образом, описатель extern позволяет только сослаться на описание, сделанное в другом месте.

Для того, чтобы описание extern было корректным, необходимо чтобы описание самой переменной существовало только один раз в любом из файлов, образующих текст программы, например:

Файл 1 файл 2 файл 3

… … …

float p=0.33; extern float p; extern float p;

Замечание: Описание вида: extern тип имя_ переменной = значение; недопустимо.

Если переменная внутри функции имеет класс памяти extern, то она может быть описана только после описания этой функции, например:

Неправильно Правильно

… …

main () main ()

{ {

… …

} }

6 func_1() func_1()

{ {

k = k+2 extern int k;

} k = k+2;

int k = 10 }

… int k =10;

Ошибка состоит в том, что область видимости переменной начинается с точки ее описания.

Глобальные переменные могут быть инициализированы:

явно: int k = 10; static float a = 20.52;

неявно int k; static float a;

При неявной инициализации переменным присваиваются нулевые значения.

Класс памяти static на внешнем уровне маскирует описание переменных внутри файла, в котором они описаны. Другим файлам они не недоступны.

Класс памяти register предполагает хранение переменной во внутреннем регистре процессора. Время жизни и область видимости регистровой переменной такая же, как и у автоматической. Если компилятор не может разместить эту переменную в регистре, то она трактуется как автоматическая. По умолчанию значение регистровых переменных не определено.

К регистровой переменной нельзя применить операцию & - определение адреса. Их нельзя описывать на внешнем уровне.

Наши рекомендации