Классы памяти.
Область действия переменных
Напомним, что все объекты перед их использованием должны быть декларированы. Одним из атрибутов в декларации объекта является класс памяти, который определяет время существования (время жизни) переменной и область ее видимости (действия). Имеется три основных места, где объявляются переменные:
внутри функции - локальные (внутренние) переменные;
при определении параметров функции - формальные параметры;
вне функции - глобальные (внешние) переменные.
Параметры функции являются локальными объектами и должны отличаться по идентификаторам от используемых в коде функции глобальных объектов. Локальные объекты, описанные в коде функции, имеют приоритет перед объектами, описанными вне функции, например:
...
int n; // глобальное n
void main (void)
{
int i;
...
f1(i);
...
f2(n); // локальное n
}
f1(int i)
{
...
i=n; // глобальное n
...
}
f2(int n)
{
int i;
...
i=n; // локальное n
...
}
Следует учитывать, что любая декларация объекта действует только на остаток файла исходного текста. В С++ допускается в разных блоках программы использовать один и тот же идентификатор объекта, тогда внутреннее объявление объекта скрывает доступ к объекту, объявленному на более высоком уровне, например:
|
|
...
void main(void)
{
int i = 3;
cout << “\n Block 1 - “ << i;
{
float i = 2.5;
cout << “\n Block 2 - “ << i;
{
char i = ‘a’;
cout << “\n Block 3 - “ << i;
}
}
cout << “\n New Block 1 - “ << ++i;
}
В результате выполнения этой программы на экране получим:
Block 1 - 3
Block 2 - 2.5
Block 3 - a
New Block 1 - 4
В языке С/C++ каждая переменная принадлежит к одному из четырех классов памяти:
1. динамическая память, которая выделяется при вызове функции и освобождается при выходе из нее, атрибуты динамической памяти:
auto - автоматический;
register - регистровый.
2. статическая память, которая распределяется на этапе трансляции и заполняется по умолчанию нулями, атрибуты статической памяти:
внешний – extern;
статический – static.
Тип памяти указывается ключевым словом (auto, extern, static, register), стоящим перед спецификацией типа переменной. Например,
register int a;
По умолчанию переменная относится к классу auto и будет размещена в стеке.
В языке С функции могут вызывать сами себя. В этом случае функция называется рекурсивной.
Пример рекурсивной функции – вычисление факториала числа n!=1*2*3*…*n:
int fac (int n)
{
int b;
if (n==1) return 1;
b= fac (n-1)*n;
return n;
}
Вызов функции в рекурсии не создает новую копию функции, а создает новые копии локальных переменных и параметров. Из рекурсивной функции надо предусмотреть выход, иначе система «зависает» через некоторое время работы с ней.