Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
(6)подпрограммы.doc
Скачиваний:
9
Добавлен:
04.08.2019
Размер:
72.19 Кб
Скачать

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

  Если некоторый параметр будет использоваться в теле подпрограммы только для

считывания данных (фактически, как константа), лучше не рассчитывать на воз-

можности компилятора, а подсказать ему об этом явно. В этом случае присваива-

ние данному параметру нового значения станет недопустимым.

Подобная подсказка осуществляется указанием зарезервированного слова const

в списке параметров, что позволяет организовать эффективную обработку соот-

ветствующего параметра, не беспокоясь о возможных изменениях его значения.

procedure Sum( const A; TBigArray ) ,-

Менять значение элементов переменной А в теле процедуры Sum теперь нельзя:

компилятор сообщит об ошибке.

Параметры-результаты

В Паскале имеется еще одна возможность передачи параметра по имени - с помощью зарезервированного слова out. Такой параметр может использоваться внутри тела подпрограммы только для присваивания значения (но не для считывания данных). По смыслу использование слова out противоположно использованию слова const. Если заголовок процедуры описан так: Procedure Sum (out A: TBigArray); То в теле процедуры Sum можно указывать операторы присваивания A[10000] := 'num172855'; Но нельзя считывать значения элементов массива A: x := A[2] * 2; // нельзя! ПОДСКАЗКА. Для получения результатов от подпрограммы всегда правильнее использовать функции. Процедуры, возвращающие результат через свои параметры, лучше применять только тогда, когда без этого не обойтись (например, параметры-результаты требуются при создании приложений СОМ и CORBA)

Передача строк фиксированной длины

Строки можно описывать, как уже говорилось ранее, двумя способами: просто как

тип string, или как тип string с конкретной длиной строки в квадратных скобках.

Однако указывать строки фиксированной длины в качестве параметров подпро-

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

procedure Sum( S: string[50] ); // неверно!

Правильно написать так:

type stringSO = string[50];

procedure Sum( S: string50 };

Передача массивов в качестве параметров

Стандартный прием Паскаля состоит в описании массива как типа данных и ука-

зании этого типа для параметра подпрограммы. Однако таким способом удается

обрабатывать только динамические массивы и статические массивы заранее задан-

ной длины. Часто требуется, чтобы подпрограмма не ограничивалась конкретными

размерами массива. Например, функция, вычисляющая сумму всех элементов мас-

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

Подпрограммы 59

ческие массивы использовать не всегда удобно и не всегда правильно, так как они

ухудшают эффективность работы программы.

В Паскале разрешается указывать в качестве параметров массив с неопределенными

границами.

procedure Sum( A: array of Byte );

Передача значений как массива

Вместо указания в параметрах при обращении к подпрограмме имени переменной-

массива можно указать непосредственно содержимое этого массива: список значе-

ний через запятую в квадратных скобках.

Sum( [1, 5, X, а+Ь*2] );

Способы вызова подпрограмм

•Подпрограммы с точки зрения прикладного программиста вызываются всегда оди-

наково, но машинный код, который создается компилятором, для разных подпро-

грамм может отличаться. Это зависит от целей применения конкретной подпро-

граммы. Она может использоваться:

в рамках разрабатываемой прикладной программы;

как функция, доступная из динамической библиотеки .DLL;

как процедура, вызываемая из внешних программ или из Windows и т. д.

Для каждого из таких нестандартных случаев вслед за заголовком подпрограммы

(за точкой с запятой) должно следовать одно из ключевых слов.

Ключевое слово Способ передачи параметров

Ключевое слово

Способ передачи параметров

pascal

Стандартный (параметры помещаются в стек)

register

Способ, применяемый по умолчанию. Аналогичен использованию ключевого

слова pascal, но параметры передаются с помощью трех регистров

процессора, а не помещаются в стек (область оперативной памяти),

что обычно приводит к повышению быстродействия программы

cdecL

В соответствии с соглашениями компиляторов для языков программирования

С и C++. Применяется, когда происходит обращение к динамическим

библиотекам DLL, написанным на этих языках

stdcall

В соответствии с соглашениями Windows

safecall

Используется при работе с компонентными технологиями

При использовании ключевых слов register и pascal вычисление параметров выпол-

няется слева направо и располагаются они в оперативной памяти перед вызовом

подпрограммы в таком же порядке. При использовании ключевых слов cdecL, stdcall

и safecall параметры располагаются в обратном порядке (справа налево).

procedure Sum( A: array of const ); stdcall;

Существует еще одно зарезервированное слово Паскаля, forward, которое, при ука-

зании вслед за заголовком, говорит компилятору о том, что в данном месте распо-

ложен только заголовок подпрограммы, а все ее описание находится в исходном

тексте далее. Такое описание обычно применяют, если в тексте имеется несколько

подпрограмм, которые вызывают друг друга по кругу. Например, из процедуры Р1

вызывается процедура Р2, а из процедуры Р2 — процедура Р1.

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

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

говом процессе (пример условный, потому что приведенная схема может приве-

сти к бесконечной цепочке вызовов) процедура Р2, вызываемая в теле процедуры Р1,

расположенной выше в исходном тексте, еще не описана, следовательно, обращаться

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

катор.__

Перегружаемые подпрограммы

Хотя в Паскале не допускается использование одинаковых названий для пере-

менных, констант и других идентификаторов, для локальных переменных и под-

программ делается исключение. Так как в Паскале предъявляются строгие требова-

ния к типам данных, обращаться к подпрограмме, формальные параметры которой

имеют тип Integer, с фактическими параметрами, имеющими тип Real, нельзя. Однако

при решении задачи подчас бывает необходимо, чтобы подпрограмма с одним и

тем же именем работала с разными типами данных.

Здесь есть два способа действий: либо использовать данные типа Variant (что чре-

вато ошибками преобразования, снижает общую эффективность программы и тре-

бует от разработчика повышенной бдительности), либо применить перегружае-

мые подпрограммы. Они отличаются от обычных подпрограмм тем, что имеют

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

пилятору, что конкретная подпрограмма — перегружаемая, надо вслед за ее заго-

ловком указать зарезервированное слово overload.

При вызове такой подпрограммы компилятор по типам параметров автоматически

определит, какую же подпрограмму конкретно надо использовать в данном месте.

Локальное описание

Сразу за заголовком подпрограммы следует локальное описание типов, переменных и

констант, локальных для данной подпрограммы и существующих только в ее грани-

цах. Такое описание подчиняется обычным правилам Паскаля. В нем разрешается

использовать слова type, var и const. Локальное описание может быть опущено.

Вложенные подпрограммы

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

локальные подпрограммы, к которым можно обращаться (вызывать) только из тела

«родительской» подпрограммы. При этом локальная подпрограмма может свободно

обращаться к любым локальным описаниям (переменным, типам), которые рас-

положены до описания данной подпрограммы.

Такая возможность полезна, когда во время кодирования подпрограмма начинает

непредвиденно разрастаться. Ее приходится делить на более мелкие фрагменты,

которые в то же время желательно не выносить за пределы текущей подпрограммы,

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

Тело подпрограммы

Тело подпрограммы заключается в логические скобки begin/end. В них располага-

ются только операторы и вызовы других подпрограмм.

Возврат значений из функции

Если описывается функция, то в ее теле надо определить, как значение будет воз-

вращено в вызываемую программу. Для этого есть два способа.

1. Соответствующее значение присваивается переменной, имя которой совпадает

с названием функции.

function Sum( А, В: Integer ): Integer;

begin

Sum := A + В

end;

Имя функции для возврата значения разрешается указывать только в левой

части оператора присваивания.

2. Соответствующее значение присваивается специальной локальной перемен-

ной Result (эту переменную описывать не надо).

function Sumf А, В: Integer ): Integer;

begin

Result := A + В

end,