Локальные и глобальные идентификаторы

Begin

<основное тело процедуры>

End;

Вызов процедур. Обратимся к примеру, приведенному на рисунке.

Procedure Sum (x,y: Integer; Var z: Integer)

Begin

Z:=x+y

End;

ReadLn(а, b, с);

Sum (a, b, c);

WriteLn (c);

В приведенном фрагменте текста программы вызывается процедура вычисления суммы двух целых чисел. Процедура вызывается по имени.

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

При вызове процедуры в нее могут передаваться данные. В нашем примере в процедуру Sum передаются переменные a, b, c. Процедура имеет три параметра x, y и z. Причем x, y описаны без идентификатора Var, а z - с идентификатором Var. Поясним разницу следующей схемой: a→x, b→y, c↔z. При вызове процедуры Sum(a,b,c) из основной программы значение переменной a присваивается переменной x процедуры Sum, а значение переменной b - переменной y. Иначе обстоит дело с переменными c и z. Процедура Sum «знает» о том, где в памяти компьютера находится переменная c и что при изменении переменной z необходимо произвести соответствующее изменение переменной c. На это указывает идентификатор Varв описании параметра z.

Использование процедур и функций в Паскале тесно связано с некоторыми особенностями работы с идентификаторами (именами) в программе. В частности, не все имена всегда доступны для использования. Доступ к идентификатору в конкретный момент времени определяется тем, в каком блоке он описан.

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

 

Основные правила работы с глобальными и локальными именами можно сформулировать так:

Локальные имена доступны (считаются известными, "видимыми") только внутри того блока, где они описаны. Сам этот блок, и все другие, вложенные в него, называют областью видимости для этих локальных имен.

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

Глобальные имена хранятся в области памяти, называемой сегментом данных (статическим сегментом) программы. Они создаются на этапе компиляции и действительны на все время работы программы.

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

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

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

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

Локальные переменные существуют только в течение времени работы процедуры, определяются (создаются) при ее вызове и «исчезают» после завершения работы процедуры (после выполнения оператора End).

Параметры. При описании процедуры указывается список формальных параметров. Каждый параметр является локальным, к нему можно обращаться только в пределах данной процедуры (в нашем примере x, y, z - формальные параметры). Фактические параметры - это параметры, которые передаются процедуре при обращении к ней (a, b, c - фактические параметры). Количество и типы формальных и фактических параметров должны совпадать.

Параметры-значения. В нашем примере фактические параметры a и b передавались “по значению”. При таком способе передачи параметров значение фактического параметра становится значением соответствующего формального параметра. Внутри процедуры можно производить любые действия с данным формальным параметром (допустимые для его типа), но эти изменения никак не отражаются на значении фактического параметра, т. Е. каким он был до вызова процедуры, таким же и останется после завершения ее работы (x,y – формальные параметры-значения).

Параметры-переменные. Это те формальные параметры, перед которыми стоит идентификатор Var. При таком способе передачи параметров в процедуру передается не значение, а адрес фактического параметра (обязательно переменной). Любые операции с формальным параметром выполняются непосредственно над фактическим параметром.

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

Концепция процедур и функций — один из механизмов второго витка развития технологий программирования, а именно, структурного проектирования.

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

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