Link: Лекция 10: Классы памяти и разработка программ
Ухх, тема не из простых
Что-то мне подсказыват, что на этой лекции многие заканчивают свое изучение С. Остаются только самые сильные. Скажем так, на момент сдачи мною теста были такие результаты 88/91. Учитывая, что курс начали порядка тысячи человек, получается, что этот рубеж прошла пятая часть.
Общая статистика тоже неутешительная: 15к начали и только 2к закончили (13%)
Хватит о грустном.
Классы памяти и область действия
Сразу же нам дается мутное описание, из которого, ваш покорный слуга так ничего и не понял, а вот пример про глобальную переменную говорит гораздо больше:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* глобальная переменная 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); } |
Результат
1 2 3 4 5 |
Сколько курсов на сайте intuit.ru? 20 Ошибка. Попытайтесь снова. 30 Посмотрите на сайте! |
Обратите внимание на ключевое слово extern оно определяет, что переменная глобальная. Для тех кто знаком с PHP можно провести аналогию со словом global. Его так же как и extern необходимо писать в функции, если мы хотим воспользоваться глобальной переменной, а не локальной с таким же именем.
Каждая переменная имеет тип и принадлежит к некоторому классу памяти.
- auto – локальный идентификатор, память для которого выделяет при входе в блок (по умолчанию в функции)
- static – локальные идентификаторы, существующие в процессе всех выполнений блока. Память выделяется в начале и переменная существует пока выполняется программа.
- extern – я не знаю, что сказать… назовем это внешним идентификатором (по умолчанию вне функции)
- register – тоже самое что и auto, только их значения, если это возможно, должны помещаться в регистрах машины для обеспечения быстрого доступа к данным.
Если идентификатор определяется внутри функции, тогда его класс памяти auto, в остальных случаях идентификатор имеет класс памяти extern.
Дальше идет много текста, где переплетаются такие понятия как “описание идентификаторая” и “определение идентификатора”. Сначала разберемся что каждый из них обозначает, лучше сделать это на примере. Т.к. с фантазией у меня сегодня туговато, поэтому возьмом предыдущий пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
int ext; /* Определение идентификатора (выделяется память) */ main( ) { extern int ext; // Описание идентификатора (память НЕ выделяется, зато проверка типа) ... critic( ); ... } critic( ) { extern int ext; // Описание идентификатора ... } |
Определение – одно, описание – много
Автоматические переменные
Ничего интересного тут не сказано. Переменная появляется при входе в блок и исчезает после его покидания. (есть еще подблоки – но это не камильфо)
Внешние переменные
Постоянные глобальные переменные инициализируются 0, если явно не задано другое начальное значение. (Вы же помните, что в C нету String, а есть только Char, который автоматически приводится к int)
Статические переменные
Если вы знакомы с PHP, то для вас не будет ничего нового. Статические переменные делятся на локальные (внутри функций) и внешние (вне функций):
Локальные статические переменные
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* Локальная статическая переменная */ main( ) { int count; for(count = 1;count <= 3; count ++) { printf("Подсчет студентов %d:\n", count); man_woman ( ); } } man_woman( ) { int man = 1; static int woman = 1; printf("юношей = %d и девушек = %d\n", man++, woman++); } |
Результат
1 2 3 4 5 6 |
Подсчет студентов 1: юношей = 1 и девушек = 1 Подсчет студентов 2: юношей = 1 и девушек = 2 Подсчет студентов 3: юношей = 1 и девушек = 3 |
Внешние статические переменные
Тут есть интересный момент:
Обычная внешняя переменная может использоваться функциями в любом файле, а внешняя статическая переменная может использоваться только функциями того же самого файла, причем после определения переменной.
Регистровые переменные
Про регистровые переменные практически ничего не сказано, одной фразой можно описать так:
Регистровые переменные запоминаются в регистрах центрального процессора, где доступ к ним и работа с ними выполняются гораздо быстрее, чем в памяти.
Операция получения адреса & неприменима к регистровым переменным.
Любые переменные в блоке, кроме формальных параметров функции, могут быть определены как статические.
Подведем итог.
Классы памяти, которые описываются внутри функции:
- автоматический, продолжительность существования – временно, область действия – локальная;
- регистровый, продолжительность существования – временно, область действия – локальная;
- статический, продолжительность существования – постоянно, область действия – локальная.
- внешний, продолжительность существования – постоянно, область действия глобальная (все файлы);
- внешний статический, продолжительность существования – постоянно, область действия – глобальная (один файл).
[toggles class=”yourcustomclass”]
[toggle title=”Какие классы памяти бывают?”]
- static
- extern
- register
- auto
[/toggle]
[toggle title=”Продолжительность существования переменной – постоянно, а область действия – глобальна (один файл). Какой класс памяти нужно использовать?”]внешний статический[/toggle]
[toggle title=”Какие классы памяти определяются вне функции?”]
- внешний, продолжительность существования – постоянно, область действия глобальная (все файлы)
- внешний статический, продолжительность существования – постоянно, область действия – глобальная (один файл)
[/toggle]
[toggle title=”Какие классы памяти описываются внутри функции?”]
- автоматический, продолжительность существования – временно, область действия локальная
- статический, продолжительность существования – постоянно, область действия локальная
- регистровый , продолжительность существования – временно, область действия локальная
[/toggle]
[toggle title=”Для чего используется регистровая память?”]
для повышения скорости работы программы
[/toggle]
[toggle title=”К каким переменным применима операция получения адреса?”]
- операция получения адреса применима к автоматическим переменным
- операция получения адреса применима к глобальным переменным
- операция получения адреса применима к статическим переменным
[/toggle]
[toggle title=”Отметьте правильно указанные области действия классов памяти:”]
- register – локальная
- auto – локальная
[/toggle]
[toggle title=”Чем отличается статическая переменная от автоматической?”]
- статические переменные имеют такую же область действия, как автоматические переменные, но они не исчезают, когда содержащая их функция закончит свою работу
- в отличие от идентификаторов типа auto, для идентификаторов типа static память выделяется только один раз – в начале выполнения программы, и они существуют, пока программа выполняется
[/toggle]
[toggle title=”К каким переменным неприменима операция получения адреса & ?”]
регистровым переменным
[/toggle]
[/toggles]