Передача параметров в подпрограммы.
В общем случае параметры у процедур и функций могут отсутствовать. В этом случае аргументы (входные параметры) и результаты (выходные параметры) передаются как глобальные переменные (объявленные в охватывающем блоке), общие для всех подпрограмм, но если надо передать значения аргументов непосредственно в подпрограмму (через заголовок – так повышается понятность программы) и получить результат непосредственно в точке вызова подпрограммы (тоже через заголовок), то при описании процедур и функций необходимо описывать и комментировать все параметры (и входные и выходные) в их заголовках. Такие описания в заголовке подпрограммы - это описания формальных параметров подпрограммы:
procedure p(a:byte; { описание параметра а}
b: char; { описание параметра b}
var c:integer; { описание параметра c});
Формальные параметры в программах на Паскале бывают двух типов:
1) . Параметры – значения (обычно это аргументы).
2) . Параметры – переменные (обычно это результаты).
Если в заголовке подпрограммы формальный параметр описан как параметр - значение, то при вызове подпрограммы значение соответствующего фактического параметра копируется в область памяти, отведенную (в момент вызова подпрограммы) под него в стеке исходя из типа соответствующего формального параметра. Все действия в теле подпрограммы всегда записываются над формальными параметрами и глобальными переменными (если они есть), а реально выполняются при вызове над копиями соответствующих фактических параметров (эти копии – в стеке) и над глобальными переменными. Вопрос только в том, что происходит дальше с измененными (если они менялись) значениями формальных параметров.
Особенностью использования параметров - значений является то, что все действия (изменения), которым будут подвергнуты в теле вызванной подпрограммы эти формальные параметры-значения подпрограммы, будут относиться лишь к копиям (в стеке) соответствующих объектов вызывающей подпрограммы (указанных как фактические параметры) и при выходе из вызываемой подпрограммы в вызывающую (подпрограмму) эти изменения не отразятся на значениях соответствующих объектов (в вызывающей подпрограмме), указанных как фактические параметры (при вызове).
При передаче параметра - переменной в стек копируется не значение фактического параметра, а адрес фактического параметра. Соответствие между формальным и фактическим параметром устанавливается таким образом, что формальный параметр становится синонимом (они занимают одну и ту же область в памяти) фактического. Это приводит к тому, что изменение формальных параметров – переменных вызывает одновременное изменение и объектов, соответствующих фактическим параметрам. Поэтому по выходу из подпрограммы изменения параметров – переменных потеряны не будут (см. рис. ниже).
На Паскале параметры - значения описываются как обычные переменные:
Формальные параметры
procedure Summa (a : byte ; b : char ;)
Параметры - переменные на Паскале описываются после слова var:
( … var c : integer; … )
Особенность формальных и файтических параметров на Паскале:
0) в заголовке процедуры или функции описание одного формального параметра отделяется от другого точкой с запятой.
1) Каждый новый тип параметра - переменной должен сопровождаться словом var.
... var c : integer ; d : byte; d - параметр-значение
var c : integer ; var d : byte; d - параметр-переменная
2) Вызов процедуры имеет следующий вид:
Summa (1, 2, l, f);
фактические параметры
3)При вызове: один фактических параметр от другого отделяется запятой (а не ‘;’).
4) При описании подпрограммы после заголовка надо ставить точку с запятой.
5) Соответствие между формальными и фактическими параметрами устанавливается по порядку их записи слева направо.
6) Количество и тип формальных и фактических параметров должны совпадать.
7) Для формальных параметров – переменных соответствующим фактическим параметром может быть только переменные (не значение).
8) Для формальных параметров – значений соответствующим фактическими параметрами могут быть константы, переменные, вызовы функций, выражения.
9) Имена формальных и фактических параметров обычно не совпадают.
копирование при вызове стек
Фактические параметры
(в вызывающей п/п) копия a область памяти под форм. пар-р x (x:=a)
Var копия b область памяти под форм. пар-р y (y:=b)
a:...; адрес с область памяти под адрес факт. пар-ра z (z:=адрес_с^)
область памяти в стеке под копии значений и адреса фактических параметров вызова |
c: ...;
вызов: p(a, b, c);
наложение при вызове
вызываемая п/п:
Procedure P (x, y : read:
Var z: char);
begin
..x:=1;
y:=2;
z:=3;
..............
end;
ПРИМЕР. Вычислить с помощью процедуры сумму 3-х чисел:
Program P;
Var описание глобальных переменных
a, b, c, s: char;
procedure summa(x, y, z: real;
var g: real);
begin описание процедуры
g:=x+y+z;
end
begin
c:=1;
b:=2; ввод значений фактических параметров
a:=3;
s:=0;
writeln(‘s=’,s); до вызова
summa(a,b,c,s); вызов процедуры
writeln(‘s=’,s); после вызова
end.
В результате выполнения данной программы на экран будет выведено две строки:
s = 0
s = 6
В этом примере x, y, z и g - в заголовке процедуры - формальные параметры. При вызове процедуры вформальные параметры примут значения соответствующих фактических:
x=a, y=b, z=c, g=s
причем g и s станут синонимами.
Что произойдет, если из заголовка удалить слово Var? Переменная g становится параметром - значением.
Что будет выведено на экран? В этом случае при вызове процедуры внутри процедуры g - примет значение 6. Это значение будет размещено в стеке и при выходе из процедуры там же и останется. Ввиду того, что не была установлена связь между фактическим и формальным параметром, значение S останется после вызова = 0. На экран будет выведено ,то значение s , которое она имела до вызова процедуры, т.е. s=0.
Дата добавления: 2016-05-28; просмотров: 2563;