Формальные и фактические параметры

Рассмотрим более подробно вопросы взаимодействия формальных и фактических параметров.

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

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

Все формальные параметры можно разбить на четыре категории:

- параметры-значения (эти параметры подпрограмма может изменить в основной подпрограмме);

- параметры-переменные (эти параметры подпрограмма может изменить в основной программе);

- параметры-константы (только в версии 7.0);

- параметры-процедуры и параметры-функции (т.е. процедурного типа).

Для каждого формального параметра следует указать имя и, как правило, тип, а в случае параметра-переменной или параметра-константы - категорию. Имена параметров могут быть любыми, в том числе и совпадать с именами объектов программы. Необходимо лишь помнить, что в этом случае параметр основной программы с таким именем становится недоступным для непосредственного использования подпрограммой. Тип формального параметра может быть практически любым, однако в заголовке подпрограммы нельзя вводить новый тип.

Например, нельзя писать

 

Function SUMM (A: array[1..100] of Real): Real;

 

Чтобы правильно записать этот заголовок, следует в основной программе ввести тип-массив, а затем использовать его в заголовке:

 

Type aArr = array[1..100] of real;

Function SUMM (A: aArr): Real;

 

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

Параметры-значения

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

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

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

Пример 2.5.

 

Procedure MIN_MAX(Max,Min: Real; n: Word);

Function Tabulir(X,Y: Integer): Real;

 

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

 

Prl(Sqr(X),Sqr(Y),A*A);

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

Определим в основной программе тип-массив.

 

Type

aArr = Array[1..] of Integer;

Var Massiv: aArr; Maxim: Integer;

 

Функция в этом случае может иметь следующий вид.

 

Пример 2.7.

 

Function Max(Mas: aArr; N: Byte): Integer;

Var Ma : Integer; i : Byte;

Begin

Ma := Mas[1];

For i:= 2 to N Do

If Ma < Mas[i] then Ma := Mas[i];

Max := Ma {Присваивание вычисл. значения имени функции}

End;

 

Пусть надо определить максимальное число из первых 35 чисел массива. Это можно сделать с помощью оператора, использующего обращение к функции: Maxim := Max(Massiv,35);

Примечание. Данная программа может работать только с массивами типа аАrr. Для массивов другого типа надо создавать другую аналогичную подпрограмму. Данная программа создает в стеке копию исходного массива, поэтому она работает медленно.

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

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

Пример 2.8. Procedure MaxMin(A: аАrr; Var Max, Min: Real; N: Word);

Здесь Max, Min- параметры-переменные, а переменные А и N - параметры-значения.

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

Type аАrr = array [1.. 100] of Integer;

то и фактический параметр должен быть переменной или типизированной константой типа аАrr.

Пример 2.9.

Использовать функцию для вычисления максимального элемента в массиве.

В основной программе определяется тип-массив.

 

Type аАrr = Array [1.. 50] of Integer;

Var Massiv: аАrr; Maxim: Integer;

 

Функция в этом случае может иметь вид:

 

Function Max(Var Mas: аАгг; N: Byte): Integer;

Var Ma : Integer; i : Byte;

Begin Ma:=Mas[1];

For i:= 2 to N Do

If Ma < Mas[i] then Ma := Mas[i];

Max := Ma

End;

 

Пусть надо определить максимальное число из первых 35 чисел массива Это можно сделать с помощью оператора:

Maxim := Max(Massiv,35);

Примечание. Эта программа лучше предыдущей тем, что в данном случае в стеке не создается копия исходного массива, что улучшает быстродействие и экономит память. Однако при такой передаче параметра возможно его нежелательное изменение (этот вариант передачи параметра допустим только в таких небольших подпрограммах, как в данном случае, когда программист может проконтролировать несанкционированное изменение параметра). Недостатком этой программы, как и ранее описанной, является то, что она может работать только с одним типом массива.

Параметры-константы

Часто в качестве параметра в подпрограмму следует передать ту или иную переменную, но изменять ее подпрограмма не должна. В этом случае нежелательно передавать этот параметр как параметр-переменную. Можно его передать как параметр-значение, однако если эта переменная имеет больший размер (массив, запись и т.д.), то копия этого параметра займет большую часть стека и даже может его переполнить. Это приводит также к уменьшению быстродействия программы. В этой ситуации параметр лучше передать как параметр-константу. Такой параметр, если он структурированного типа, передается своим адресом, но предусматривается защита от его изменения. Использовать параметр-константу можно только в версии Турбо Паскаля 7.0.

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

Пример 2.10.Function NewString(Const S: String): String;

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

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

Пример 2.11.

Функция вычисления максимального элемента в массиве, и в качестве первого параметра – параметр-константа.

 

Function Max(Const Mas: аАrr; N: Byte): Integer;

Var Ma : Integer; i : Byte;

Begin

Ma := Mas[1];

For i:= 2 to N Do

If Ma < Mas[i] then Ma := Mas[i];

Max := Ma

End;

Параметры без типа

В Турбо Паскале можно использовать параметры-переменные и параметры-константы без указания типа. В этом случае фактический параметр может быть переменной любого типа,а ответственность за правильное использование того или иного параметра возлагается на программиста.

Пример 2.12.Function Tqual(Var Param1, Param2; Len: Word):Boolean;

Здесь Param1, Param2 - параметры-переменные без типа (вместо них можно использовать, например, любые переменные простого типа, типа-массив, типа-запись и т.д.); Len - параметр-значение.

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

Пример 2.13.Функция вычисления максимального элемента в массиве. При этом в качестве первого параметра используется параметр-переменная без типа:

 

Function Max(Var Masr; N: Byte): Integer;

Type aArray = array[Maxint] of Integer; {тип массива максимального размера}

Var Ма : Integer; i : Byte;

Begin Ма := aArray(Mas)[1];

For i:= 2 to N Do

If Ма < aArray(Mas)[i] then Ма := aArray(Mas)[i];

Max := Ма

End;

 

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