Новосибирский Государственный Университет
Опубликован: 26.08.2005 | Доступ: свободный | Студентов: 17192 / 2755 | Оценка: 4.07 / 3.55 | Длительность: 13:11:00
ISBN: 978-5-9556-0057-4
Лекция 10:

Классы памяти и разработка программ

< Лекция 9 || Лекция 10: 12 || Лекция 11 >
Аннотация: Классы памяти и область действия. Автоматические переменные. Внешние переменные. Статические переменные. Внешние статические переменные. Регистровые переменные.

Классы памяти и область действия

Классы памяти языка Си дают возможность определить, с какими функциями связаны какие переменные, и как долго переменная сохраняется в программе. Мы уже упоминали, что локальные переменные известны только функциям, содержащим их. В языке Си предполагается также, что о глобальных переменных знают сразу несколько функций:

/* глобальная переменная ext */
int ext; /* внешняя переменная */
main( )
{
	extern int ext;
	printf("Сколько курсов на сайте intuit.ru?\n");
	scanf("%d",&ext);
	while(ext != 30)
	critic( );
	printf("Посмотрите на сайте!\n");
}
critic( )
{
	extern int ext;
	printf("Ошибка. Попытайтесь снова.\n");
	scanf("%d",&ext);
}

Результат:

Сколько курсов на сайте intuit.ru?
20
Ошибка. Попытайтесь снова.
30
Посмотрите на сайте!

Мы сделали переменную ext внешней, описав ее вне любого определения функции. Внутри функции, использующей эту переменную, мы объявляем ее внешней при помощи ключевого слова extern, предшествующего спецификации типа переменной. Компилятор ищет определение этой переменной вне функции. Если бы мы опустили ключевое слово extern в функции critic( ), то компилятор создал бы в функции critic новую переменную и тоже назвал бы ее ext. Тогда другая переменная ext, которая находится в main( ), никогда не получила бы нового значения.

Каждая переменная имеет тип и принадлежит к некоторому классу памяти. Время жизни и область действия идентификатора определяются ассоциированным с ним классом памяти. Существуют четыре разновидности классов памяти:

auto - автоматический - локальные идентификаторы, память для которых выделяется при входе в блок, т.е. составной оператор, и освобождается при выходе из блока. Слово auto является сокращением слова automatic.

static - статический - локальные идентификаторы, существующие в процессе всех выполнений блока. В отличие от идентификаторов типа auto, для идентификаторов типа static память выделяется только один раз - в начале выполнения программы, и они существуют, пока программа выполняется.

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

register - регистровый - идентификаторы, подобные идентификаторам типа auto. Их значения, если это возможно, должны помещаться в регистрах машины для обеспечения быстрого доступа к данным.

Если класс памяти идентификатора не указан явно, то его класс памяти задается положением его определения в тексте программы. Если идентификатор определяется внутри функции, тогда его класс памяти auto, в остальных случаях идентификатор имеет класс памяти extern.

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

! При описании внешних массивов максимальное значение первого индекса массива указывать нет необходимости. Оно будет получено из соответствующего определения, что создает дополнительные удобства для пользователя.

Для внешнего идентификатора память выделяется только в том случае, если класс памяти не указан явно.

! Явное указание памяти extern является отличительным признаком внешнего описания от внешнего определения.

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

Определение класса памяти переменной зависит от того, где переменная описана и какое ключевое слово, если оно есть, используется.

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

Автоматические переменные

По умолчанию переменные, описанные внутри функции, являются автоматическими. Можно, однако, это подчеркнуть явно с помощью ключевого слова auto:

main( ) 
{
	auto int kat;
}

Так поступают, если хотят, например, показать, что определение переменной не нужно искать вне функции.

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

Автоматическая переменная начинает существовать при вызове функции, содержащей ее. Когда функция завершает свою работу и возвращает управление туда, откуда ее вызвали, автоматическая переменная исчезает. Область действия автоматической переменной ограничена блоком, т.е. { }, в котором переменная описана.

! Мы всегда должны описывать наши переменные в начале тела функции (блока). Областью действия их является вся функция. Можно описать переменную внутри подблока. Тогда переменная будет известна только в этой части функции, однако этого лучше не делать. Это дурной стиль программирования!
< Лекция 9 || Лекция 10: 12 || Лекция 11 >
Вадим Ратьков
Вадим Ратьков

Объясните, пожалуйста, чем отличаются два этих кода?

printf("смешанное деление: 7./4 это %2.2f \n", 7./4);

и

printf("смешанное деление: 7./4 это %f \n", 7./4);

%f  это, понятное дело, float. А что такое %2.2f ?

Вопрос возник при прочтении лекции 3 часть вторая курса Основы программирования на языке C.

http://www.intuit.ru/studies/courses/43/43/lecture/1281?page=2

Анна Алексанина
Анна Алексанина

Я хочу выполнить одну из программ, которые есть в лекции. Но для этого мне надо компилировать текст, а я не знаю, как это сделать. ОС Windows.

Николай Алешин
Николай Алешин
Россия
Наталия Смагина
Наталия Смагина
Россия, г. Самара