Классы памяти, время жизни и область видимости программных объектов. Инициализация локальных и глобальных переменных.

Время жизни и область видимости программных объектов

Время жизни переменной (глобальной или локальной) определяется по следующим правилам.

1. Переменная, объявленная глобально (т.е. вне всех блоков), существует на протяжении всего времени выполнения программы.

2. Локальные переменные (т.е. объявленные внутри блока) с классом памяти register или auto, имеют время жизни только на период выполнения того блока, в котором они объявлены. Если локальная переменная объявлена с классом памяти static или extern, то она имеет время жизни на период выполнения всей программы.

Видимость переменных и функций в программе определяется следующими правилами.

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

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

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

4. Функции с классом памяти static видимы только в исходном файле, в котором они определены. Всякие другие функции видимы во всей программе.

Метки в функциях видимы на протяжении всей функции.

Имена формальных параметров, объявленные в списке параметров прототипа функции, видимы только от точки объявления параметра до конца объявления функции.

Инициализация глобальных и локальных переменных

При инициализации необходимо придерживаться следующих правил:

1. Объявления содержащие спецификатор класса памяти extern не могут содержать инициаторов.

2. Глобальные переменные всегда инициализируются, и если это не сделано явно, то они инициализируются нулевым значением.

3. Переменная с классом памяти static может быть инициализирована константным выражением. Инициализация для них выполняется один раз перед началом программы. Если явная инициализация отсутствует, то переменная инициализируется нулевым значением.

4. Инициализация переменных с классом памяти auto или register выполняется всякий раз при входе в блок, в котором они объявлены. Если инициализация переменных в объявлении отсутствует, то их начальное значение не определено.

5. Начальными значениями для глобальных переменных и для переменных с классом памяти static должны быть константные выражения. Адреса таких переменных являются константами и эти константы можно использовать для инициализации объявленных глобально указателей. Адреса переменных с классом памяти auto или register не являются константами и их нельзя использовать в инициаторах.

Пример: int global_var; int func(void) { int local_var; /* по умолчанию auto */ static int *local_ptr=&local_var; /* так неправильно */ static int *global_ptr=&global_var; /* а так правильно */ register int *reg_ptr=&local_var; /* и так правильно */ }

В приведенном примере глобальная переменная global_var имеет глобальное время жизни и постоянный адрес в памяти, и этот адрес можно использовать для инициализации статического указателя global_ptr. Локальная переменная local_var, имеющая класс памяти auto размещается в памяти только на время работы функции func, адрес этой переменной не является константой и не может быть использован для инициализации статической переменной local_ptr. Для инициализации локальной регистровой переменной reg_ptr можно использовать неконстантные выражения, и, в частности, адрес переменной local_ptr.

Класс памяти

Класс памятиопределяет порядок размещения объекта в памяти.

Различают автоматический и статический классы памяти. C располагает четырьмя спецификаторами класса памяти:

autoregisterstaticextern

Спецификаторы позволяют определить класс памяти определяемого объекта:

Auto.

Этот спецификатор автоматического класса памяти указывает на то, что объект располагается в локальной (или автоматически распределяемой) памяти. Он используется в операторах объявления в теле функций, а также внутри блоков операторов, ограниченных фигурными скобками.

Объекты, имена которых объявляются со спецификатором auto, размещаются в локальной памяти непосредственно перед началом выполнения функции или блока операторов, ограниченного фигурными скобками {}. При этом размер выделяемой памяти известен ещё на этапе компиляции программы, поэтому при компиляции могут быть применены специальные процедуры, оптимизирующие выделение памяти. Такая процедура выделения памяти называется статическим распределением памяти(не путать со статическим классом памяти).

При выходе из блока или при возвращении из функции, соответствующая область локальной памяти освобождается и все ранее размещённые в ней объекты уничтожаются. Таким образом спецификатор влияет на время жизни объекта (это время локально). Спецификатор auto используется редко, поскольку все объекты, определяемые непосредственно в теле функции или в блоке операторов и так по умолчанию имеют автоматический класс хранения и располагаются в локальной памяти. Класс хранения таких объектов, как аргументы функций, также называется автоматическим. Такое название означает, что область памяти для хранения этих элементов данных выделяется автоматически при вызове функции и также автоматически освобождается, когда исполнение этой функции завершается, т. е. временем жизни аргументов является продолжительность исполнения функции. Как только функция завершает работу, их значения будут утеряны.

Пример использования: auto int i;

Register.

Ещё один спецификатор автоматического класса памяти. Применяется к объектам, по умолчанию располагаемым в локальной памяти. Представляет из себя "ненавязчивую просьбу" к транслятору (если это возможно) о размещении значений объектов, объявленных со спецификатором register в одном из доступных регистров, а не в локальной памяти. В этом случае доступ к таким еременным осуществляется гораздо быстрее. Если по какой-либо причине в момент начала выполнения кода в данном блоке операторов регистры оказываются занятыми, транслятор обеспечивает с этими объектами обращение, как с объектами класса auto. Очевидно, что в этом случае объект располагается в локальной области памяти. Область действия и время жизни полностью идентичны классу auto.

Пример использования: register int i;

Static.

Спецификатор внутреннего статического класса памяти. Применяется только(!) к именам объектов и функций (не применяется к аргументам функций). В C++ этот спецификатор имеет два значения.

Первое означает, что определяемый объект располагается по фиксированному адресу. Тем самым обеспечивается существование объекта с момента его определения до конца выполнения программы (время жизни – всё время работы программы, хотя переменная и может быть определена локально). В отличие от объекта класса памяти auto, объект не будет уничтожаться при выходе из функции, где он был объявлен.

Например, при каждом вызове функции IncS(), объявленной следующим образом:

void IncS()

{

int f=1;

static int s=1;

f++;

s++;

}

значение переменной f в начале выполнения функции будет равно 1, в ходе выполнения функции оно увеличится на 1, а в конце выполнения f уничтожится. Значение же переменной s будет увеличиваться на 1 при каждом вызове функции, т.к. переменная s является статической и не уничтожается на протяжении всей программы. Отметим также, что при такой записи значение 1 присваивается переменной s только один раз – при инициализациив момент создания переменной. При последующих вызовах функции эта строчка игнорируется.

Второе значение спецификатора static означает локальность. Объявленая со спецификатором static переменная или функция локальна в одном программном модуле (то есть, недоступна из других модулей многомодульной программы). Может использоваться в объявлениях как внутри блоков и функций, так и вне их (в этом случае мы получаем внешнюю статическую переменную).

Extern

Спецификатор внешнего статического класса памяти. Спецификатор extern позволяет функции использовать внешнюю переменную, даже, если она определяется позже в этом или другом модуле.

Внешниминазываются переменные, объявленные вне функции. Поскольку при таком описании к ним автоматически получают доступ все функции этого модуля, то таки переменные также называют глобальными. С помощью спецификатора extern можно получить доступ к внешней переменно и из другого модуля, для чего они чаще всего и применяются.

Extern является своего рода модификатором-ссылкой, указывающим на то, что где-то такая переменная уже описана. И поэтому в процессе компиляции не следует выделять под неё память именно здесь, а следует найти такую внешнюю переменную в других модулях на стадии компоновки. Если такая переменная найдена не будет, то компоновщик выдаст ошибку «Объект не найден».

Пример:

Module MAIN.CPP

/* определить внешние данные*/

extern int iValue1;

extern int iValue2;

main()

{

save()

printf ("значения равны: %d %d \n", iValue1, iValue2);

}

Module SAVE.CPP

/*определить внешние данные */

int iValue1;

int iValue2;

save()

{

iValue1=10;

iValue1=15;

return;

}

Глобальные переменные iValue1 и iValue2 объявлены в обоих модулях, но память под них выделяется только в модуле Save.cpp. В модуле Main.cpp они объявлены с модификатором extern, это сделано только для того, чтобы получить доступ к этим глобальным переменным.

Спецификатор extern можно использовать и внутри функций, например:

main()

{

extern int iValue1;

extern int iValue2;

save()

printf ("значения равны: %d %d \n", iValue1, iValue2);

}

В этом случае доступ к переменным iValue1, iValue2 другого модуля будет иметь только эта функция, в остальных их придётся декларировать заново. Такая форма записи встречается доволно редко.

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

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

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