Информатика -продвинутый курс


КЛАССЫ ПАМЯТИ


Помимо изученных ранее характеристик переменных (имени, типа, значения), в ряде случаев оказывается важной еще одна - класс памяти. Класс памяти характеризует время существования и место хранения объекта в программе.

Для обозначения класса памяти в языке Си используются следующие служебные слова:

auto                 extern

register            static

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

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

Объекты, описанные внутри блока с классом памяти register, называются регистровыми переменными. Они подчиняются всем правилам, касающимся автоматических переменных. Описание register указывает компилятору, что данная переменная будет часто использоваться. Когда это возможно, переменные, описанные как register, располагаются в машинных регистрах. Это приводит к меньшим по размерам и более быстрым программам.

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

Внешние объекты делятся на внешние глобальные и внешние статические.

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

Например, появившиеся вне определения какой-либо функции строчки



int max;

char save[maxline];

определяют внешние переменные max и save, вызывают отведение для них места в памяти и служат в качестве описания для остальной части этого файла. В то же время строчки

extern int max;

extern char save[];

описывают в остальной части данного блока переменную max как int, a save как массив типа char (размеры которого указаны в другом месте), но не создают переменных и не отводят для них места в памяти.

Во всех блоках, составляющих исходную программу, должно содержаться только одно определение внешней переменной; другие блоки могут содержать описания extern для доступа к ней.

Программа 103

#include<stdio.h>

int i=0;

/* Класс памяти переменной - внешний. Область действия переменной -любая программа, */

/* загружающаяся с данным файлом. Время существования i=0 - все время выполнения программы. */

main()                                              /* Блок уровня 1. */

(

auto int i=l;

/* В блоке 1 область действия i=l - функция main(). Время */

/* существования i=l - все время выполнения главной функции /*

/* main(). /*

printf("%d\n", i) ;

/* Если две переменные имеют одно и то же имя, то по этому */

/* имени обращаются к внутренней переменной, внешняя */

/* непосредственно недоступна, поэтому после выполнения */

/* блока 1 программа напечатает i=l. */

{     /* Блок уровня 2. */

int i=2;

/* Класс памяти переменной i=2 - auto. Область */

/* действия i=2 - блок 2, время существования - время */

/* существования блока 2.


блок 2, время существования -*/

/* время существования блока 2. */

printf("%d\n", i) ;

/* Программа напечатает i=2. */

{     /* Блок

уровня 3. */

i+=l; printf("%d\n", i);

/* Печатается самая внутренняя переменная с именем i,/*

/* которая после выполнения операции данного блока */

/* становится равной 3. */

}

/* Возвращение к блоку уровня 2. */

printf("%d\n", i) ;

/* Опять печатается i=3. */

)

/* Возвращение к блоку уровня 1. */

printf("%d", i) ;

/* Переменная i=3 исчезает. Теперь самой внутренней переменной */

/* с именем i будет i=l. */

)

Программа 104

#include<stdio.h>

int a;

main()

(

extern int a;

int P ();

a=6; P();

)

int P()

(

extern int a;

printf("a=%d",a);

}

Результат работы программы:

a=6

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

static <Спецификация типа> <Спецификация данных>;

На основании определения под объект отводится память и может быть произведена инициализация. Статические переменные можно инициализировать только выражениями с константами и с указателями на ранее описанные объекты.

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

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



Константы являются объектами статического класса памяти.

Функция может быть определена как статический внешний объект. В этом случае она будет доступной в любой точке данного мод\ля и не доступной за пределами модуля.

Программа 105

#include<stdio.h>

main()

(

int count;

int trystat () ;

for (count=l; count<=3; count++)

(

printf ("Итерация %d:\n", count);

trystat() ;

}

)

trystat ()

{

int fade=l;

static int stay=l;

printf("fade = %d и stay = %d\n", fade++, stay++) ;

}

Результат работы программы:

Итерация 1:

fade = 1 и stay = 1

Итерация 2:

fade = 1 и stay = 2

Итерация 3:

fade = 1 и stay = 3

Если мы лишь немного видоизменим в программе функцию trystat()

trystat()

{

int fade=l;

int stay=l;

printf("fade = %d и stay = %d\n", fade++, stay++);

}

то получим следующий результат:

Итерация 1:

fade = 1 и stay = 1

Итерация 2:

fade = 1 и stay = 1

Итерация 3:

fade = 1 и stay = 1


Содержание раздела