Как уже было отмечено, память для переменных выделяется при старте того блока, в котором объявлены эти переменные, и освобождается после окончания работы этого блока. Следовательно, при старте основной программы память будет выделена лишь для описанных в ее разделе Varпеременных x, y, z, k, m, n. Этим переменным в машинной программе будут соответствовать конкретные адреса полей памяти.
При обращении к процедуре P1 дополнительно выделяется память для описанных в ней переменных x, y, q, m, u, а после обращения к ее внутренней процедуре PP1 - также для переменных y, t, n. Следовательно, переменная y типа real, объявленная в основной программе, переменная y типа word из процедуры P1 и переменная y типа byte из процедуры PP1 имеют разные адреса памяти, т.е. на уровне Паскаль-программы они считаются разными переменными. После окончания работы процедуры PP1 память, отведенная для переменных y, t и n, освобождается; после окончания работы процедуры P1 освобождается также память, занятая переменными x, y, q, m, u.
Область действия переменной - это тот участок программы, где имени переменной ставится в соответствие один и тот же машинный адрес. В Паскаль-программе областью действия переменной является весь блок, в котором объявлена данная переменная, за исключением тех внутренних блоков, в которых эта же переменная объявлена повторно.
В рассматриваемом примере область действия переменной x, объявленной в основной программе, - вся программа, за исключением процедуры P1; переменной k - вся программа, в том числе и процедуры P1, PP1, P2; переменной q - процедура P1, в том числе и ее внутренняя процедура PP1; переменной t - только процедура PP1 и т.д.
Переменные, объявленные в основной программе, действуют во всей этой программе. Такие переменные называют глобальными (в программе SubRout - это переменные x, y, z, k, m, n ). Переменные, объявленные в процедуре, действуют лишь в пределах этой процедуры. Это локальные переменные. Более общее определение:
- локальными называют переменные, которые объявлены в разделах Varпроцедур и функций;
- глобальными называют переменные, которые объявлены в разделах Var вне процедур и функций.
При рассмотрении модулей пользователя будет указано, что глобальными являются не только переменные, объявленные в основной программе. Формальное отличие между локальными и глобальными переменными определяется местом их объявления: в блоках процедур и функций или вне этих блоков.
Для размещения переменных в оперативной памяти выделяются две области, которые называются соответственно сегментом данных и сегментом стека. Все глобальные переменные размещаются в сегменте данных при старте основной программы. Следовательно, адреса этих переменных не изменяются в течение всего времени работы программы. Максимальный размер сегмента данных равен 65520 байт, его реальный размер определяется общим объемом глобальных переменных.
Локальные переменные размещаются в сегменте стека. Память им выделяется при каждом старте соответствующей процедуры или функции. Следовательно, при повторном обращении к процедуре локальная переменная может получить адрес, не совпадающий с тем, который она имела при предыдущем обращении к этой же процедуре. Размер сегмента стека может быть задан программистом в диапазоне от 1024 до 65520 байт. По умолчанию он равен 16384 байта.
Правила, определяющие область действия метки, несколько отличаются от правил, рассмотренных выше по отношению к области действия имен.
Как известно, метка используется в программе только оператором Goto, который производит передачу управления к оператору, отмеченному соответствующей меткой. При этом по правилам языка Паскаль запрещается переход вовнутрь сложного оператора (оператор цикла, условный оператор, составной оператор и др.). Раздел операторов процедуры - это составной оператор (Begin .. End). Следовательно, переход во внутреннюю область процедуры из основной программы или из другой процедуры с помощью оператора Gotoнедопустим. Вход в процедуру возможен лишь с ее начала путем обращения к этой процедуре.
С учетом вышесказанного областью действия метки является весь блок, в котором объявлена данная метка, за исключением внутренних блоков вне зависимости от наличия в них объявления меток.
Принудительный выход из процедуры можно осуществить с помощью оператора Goto.
Пример:
Procedure P3;
Label10;
Varx : real;
Begin
...............
Ifx<0 then
Goto 10;
...............
10:
End { P3 };
Эта же работа может быть выполнена оператором Exit, осуществляющим выход за пределы блока процедуры:
Procedure P3;
Varx : real;
Begin
...............
Ifx<0 then
Exit;
...............
End { P3 };
Оба варианта процедуры P3 действуют совершенно одинаково, но второй вариант предпочтительнее, поскольку в нем не используется в явном виде оператор Goto.
Ранее было указано на два преимущества использования процедур:
- уменьшение текста программы и ее объема в памяти;
- улучшение читаемости программы.
Очень важно еще одно преимущество, определяемое тем, что выделение памяти для объявленных в процедуре переменных происходит только при ее активизации, т.е. при старте процедуры. После окончания работы процедуры память, занятая этими переменными, освобождается.
Предположим, что в программе используются три отдельные процедуры, в каждой из которых объявлен один массив, требующий соответственно 10, 20 и 30 Кбайт памяти. Если бы эти массивы были объявлены в основной программе, то для них при старте программы было бы выделено 60 Кбайт памяти. Поскольку указанные процедуры не работают одновременно, то для массивов выделяется не более чем 30 Кбайт. Следовательно, аппарат локальных переменных в процедурах является дополнительным источником экономии памяти в программе.