Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебник.docx
Скачиваний:
48
Добавлен:
21.12.2018
Размер:
2.15 Mб
Скачать

Параметры-переменные

Если перед именем формального параметра стоит ключевое слово var, то такой параметр есть параметр-переменная. Примерами таких параметров служат x1 и x2 в заголовке

procedure sq(a, b, c: real; var x1, x2: real);

Фактический параметр, соответствующий параметру-переменной, может быть только переменной (не константой и не выражением).

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

Пример. При вызове процедуры sq оператором sq(p, q, r, y, z) для переменных x1 и x2 используются непосредственно те ячейки, которые отведены для y и z. Поэтому оператор присваивания x1 := (-b + sqrt(d)) / (2 * a) засылает полученное значение в y.

Под формальные и фактические параметры-значения транслятор отводит разные области памяти. Поэтому результат выполнения процедуры может быть передан только через параметр-переменную.

var

a, b: integer;

procedure h(x: integer; var y: integer);

begin

x := x + 1;

y := y + 1;

writeln(x, y)

end;

begin

a := 0;

b := 0;

h(a, b);

writeln(a, b);

readln

end.

Результаты, выдаваемые процедурой h – 11; основная ветка программы выводит 01.

Разберем этот пример: фактический параметр a соответствует формальному параметру-значению x, а фактический параметр b – формальному параметру-переменной y. Под параметры a и x отведены две разные ячейки памяти, а под b и y – одна и та же ячейка.

При обращении к h(a, b) из ячейки a пересылается значение 0 в ячейку x, а в ячейку y засылается адрес ячейки b, содержащей 0, т.к. в процедуре h параметр x – это параметр-значение, а y – параметр-переменная.

При выполнении оператора x := x + 1 в ячейку x прибавляется 1 и в ячейке x окажется 1, а в ячейке a по-прежнему 0.

Выполнение оператора y := y + 1 имеет следующий смысл: «взять число из ячейки, адрес которой находится в y (т.е. из ячейки b), прибавить 1 и заслать в ту же ячейку (т.е. в b)».

Поэтому в результате выполнения оператора y := y + 1 значение ячейки b станет 1. Оператор печати из процедуры выдаст содержимое ячейки x и ячейки y, т.е. 1 и 1. Оператор печати в программе напечатает содержимое a, которое осталось равным 0, и содержимое ячейки b, которое теперь равно 1.

Проц едуры в Паскале допускают рекурсию, т.е. процедура может вызвать сама себя.

Если в процедуре p есть обращение к процедуре q, описанной ниже, то перед описанием p процедура q декларируется как forward: после заголовка процедуры q ставится двоеточие, а затем ключевое слово forward. В этом случае параметры процедуры описываются только в операторе с forward. В заголовке самой процедуры параметры опускаются.

Пример.

procedure q(x: t1): forward;

procedure p(x: y);

begin

q(a)

end;

procedure q;

begin

p(b)

end;

Побочные эффекты

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

Пример. Пусть функция f(x) имеет такой вид:

function f(x: real): real;

begin

v := v * x;

f := sqrt(v) + x

end;

т.е. в процессе работы функция f изменяет некоторую нелокальную величину v. Рассмотрим теперь два выражения, которые вычисляются в программе: f(x) + v и v + f(x).

Эти выражения дадут разные результаты, т.к. в первом случае к f(x) прибавляется уже измененное значение v (в процессе работы f), а во втором случае к первоначальному значению v добавляется f(x).

Вторая опасность заключается в неправильном использовании параметров-переменных в качестве формальных параметров.

Пример. Найти 5-й член последовательности

an + 1 = 3an – 2,

a1 = 1.

Опасно оформлять функцию в виде

function f(var a, n: integer): integer;

var i: integer;

begin

for i := 1 to n do

a := 3 * a – 2;

f := a

end;

Так, если обратиться к этой функции оператором b := f(1, 5), будет «испорчена» константа 1, т.к. в ячейку памяти (первый фактический параметр), содержавшую ранее единицу, функция f поместит текущий член последовательности, и при дальнейшей работе программы вместо 1 будет использоваться значение a5. Такие ошибки бывает трудно найти, поэтому полезно придерживаться следующего правила: в функциях не использовать параметры переменные.