Содержание
Области действия имён
Разграничение контекстов
Глобальные объекты — это типы данных, константы и переменные, объявленные в начале программы до объявления любых подпрограмм. Эти объекты будут видны во всей программе, в том числе и во всех её подпрограммах. Глобальные объекты существуют на протяжении всего времени работы программы.
Локальные объекты объявляются внутри какой–нибудь подпрограммы и «видны» только этой подпрограмме и тем подпрограммам, которые были объявлены как внутренние для неё. Локальные объекты не существуют, пока не вызвана подпрограмма, в которой они объявлены, а также после завершения её работы.
Таблица 8.1. Пример разграничения контекстов program prog; var a : Byte; | ||
procedure pr1 {p : Byte}; var b : Byte; {первый уровень вложенности} | ||
function f(pp : Byte); var c : Byte; {второй уровень вложенности} begin {здесь «видны» переменные a, b, c, p, pp} end; | ||
begin {здесь «видны» переменные a, b, p} end; | ||
var g : Byte; | ||
procedure pr2; var d : Byte; {первый уровень вложенности} begin {здесь видны переменные a, d, g} end; | ||
begin {тело программы; здесь «видны» переменные a, g} end; |
Побочный эффект
Поскольку глобальные переменные видны в контекстах всех блоков, то их значение может быть изменено изнутри любой подпрограммы. Этот эффект называется побочным, а его использование очень нежелательно, потому что может стать источником непонятных ошибок в программе.
Чтобы избежать побочного эффекта, необходимо строго следить за тем, чтобы подпрограммы изменяли только свои локальные переменные (в том числе и параметры–переменные).
Совпадение имён
Вообще говоря, совпадения глобальных и локальных имён допустимы, поскольку к каждому локальному имени неявно приписано имя той подпрограммы, в которой оно объявлено. Таким образом, в приведённом выше примере (см. пример 8.1) фигурируют переменные a, g, pr1.p, pr1.b, pr1.f.pp, pr1.f.c, pr2.d.
Если имеются глобальная и локальная переменные с одинаковым именем, то изнутри подпрограммы к глобальной переменной можно обратиться, приписав к ней спереди имя программы:
<имя_программы>.<имя_глобальной переменной>
Например, (локальной переменной здесь присваивается значение глобальной):
Замечание: Несмотря на то, что совпадения имён локальных и глобальных переменных не вызывают никаких коллизий на уровне компилятора, стоит всё–таки воздерживаться от них, потому что они также могут стать причиной непредвиденного побочного эффекта, аналогичного описанному в предыдущем пункте.
Нетипизированные параметры
В объявлении подпрограммы можно не указывать тип параметра–переменной:
Такой параметр будет называться нетипизированным. В этот параметр можно передать аргумент, относящийся к любому типу данных.
Для того, чтобы внутри самой подпрограммы корректно обрабатывать значения, поступившие через нетипизированный параметр, существует два различных способа.
Явное преобразование типа
При помощи операции явного преобразования типа данных (см. лекцию 2) можно преобразовать нетипизированное значение, относящееся к нужному типу данных. Например, в процедуре proc5 значение одного и того же параметра х интерпретируется трёмя разными способами: как целое число, как вещественное число и как массив:
type arr = array[1 .. 10] of Byte;
var x : Integer;
z : Real;
m : arr;
begin
{...}
y := Integer(x);
z := Real(x);
m := arr(x);
{...}
end;
Совмещение в памяти
Второй способ: описать внутри подпрограммы локальную переменную, которая будет физически совпадать с переменной, передаваемой через нетипизированный параметр:
<локальная_переменная>: <тип> absolute <нетипизир_параметр>;
В этом случае будут совмещены значения, физически записанные в этих переменных, в точности так же, как это происходит при подстановке аргумента в параметр–переменную, однако без контроля за совпадением типов данных. Поэтому вполне возможна, например, ситуация, когда первые четыре байта строки (аргумента, переданного в нетипизированный параметр) будут восприниматься как LongInt–число:
var xxx : LongInt absolute x;
begin
{ здесь с началом любой переменной,
поступившей в параметр х,
... можно обращаться как с LongInt–числом:
при помощи локальной переменной ххх }
end;