- •Процедуры и функции
- •Процедуры
- •Пример Вызов процедуры InpInt для ввода k целых чисел в массив m.
- •Функции
- •Формальные и фактические параметры
- •Параметры-значения Параметры-значения передаются основной программой в подпрограмму через стек в виде их копий. Сам параметр программы подпрограммой измениться не может.
- •Параметры-переменные
- •Этот вариант лучше предыдущего, так как в стеке не создается копия исходного массива, что улучшает быстродействие и экономит память.
- •Локализация имен
- •Пример Структура вложенной программы.
- •Основное правило Паскаля
- •Допустимые вызовы процедуры
- •Совместимость и преобразование типов данных
- •Параметры-массивы и строки открытого типа
- •Процедурные типы
- •Проблема совместимости
- •Рекурсия
- •Побочный эффект
- •Рекурсивная функция
- •Стеки для локальных переменных и параметров
- •Реализация стеков параметров в Паскале
Параметры-переменные
При передаче параметров-переменных в подпрограмму фактически через стек передаются их адреса в порядке, объявленном в заголовке подпрограммы. Следовательно, подпрограмма имеет доступ к этим параметрам и может их изменять.
Параметры-переменные указываются в заголовке подпрограммы аналогично параметру-значению, но только перед именем параметра пишется зарезервированное слово var. Его действие распространяется на все переменные, указанные до ближайшей точки с запятой, то есть в пределах одной группы.
Пример
procedure maxmin(a:tArr; var max, min :real; n :word);
Тип параметров-переменных может быть любым, включая файловый.
При вызове подпрограммы на месте параметра-переменной в качестве фактического параметра должна использоваться переменная идентичного типа.
Пример Функция вычисления максимального элемента в массиве.
type tarr = array [1..100] of integer;
{фактический параметр должен быть переменной или типизированной константой типа tarr}
function max (var mas:tarr; 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;
Этот вариант лучше предыдущего, так как в стеке не создается копия исходного массива, что улучшает быстродействие и экономит память.
Однако, при такой передаче параметра возможно его нежелательное изменение.
Подпрограмма по-прежнему может работать с одним типом массивов.
Параметры-константы
Условие – параметр передается в подпрограмму, но изменять его подпрограмма не должна. Нежелательно передавать параметр как
параметр-переменную. Можно передать как параметр-значение, но если этот параметр имеет большой размер (массив, запись и т.д.), то копии могут занять большую часть стека или даже переполнить его. Это ведет к уменьшению быстродействия программы. В этой ситуации параметр лучше передать как параметр-константу. Такой параметр, если он структурного типа, передается своим адресом, но предусмотрена его защита от изменений (версия 7.0).
Параметр-константа указывается в заголовке подпрограммы аналогично параметру-значению, но перед именем параметра записывается зарезервированное слово const. Действие слова const распространяется до ближайшей точки с запятой, т.е. в пределах одной группы.
Пример
function NewString (const s :string) :string;
Тип параметра-значения может быть любым, кроме файлового.
При вызове подпрограммы на месте параметра-константы в качестве фактического параметра можно использовать любое выражение совместимого для присваивания типа, не содержащего файловую компоненту.
Параметр-константу нельзя передавать в другую подпрограмму в качестве фактического параметра.
Пример Функция вычисления максимального элемента в массиве.
function max(const mas: tarr;n: byte): integer;
var
ma:integer;
i:byte;
begin
ma:=mas[1];
for i:=1 to n do
if ma<mas[i] then ma:=mas[i];
max :=ma;
end;
Пример
const
a: integer = 5;
b: integer = 7;
procedure inc(var c: integer; b: integer)
begin
c:= c+c;
b:= b+b;
writeln(‘удвоенные : ’,c: 5, b: 5);
end;
begin
writeln(‘исходные : ’,a: 5, b: 5);
inc(a,b);
writeln(‘результат : ’,a: 5,b: 5);
end.
исходные : |
5 |
7 |
удвоенные : |
10 |
14 |
результат : |
10 |
7 |
b – параметр-значение
При вызове вычисляется значение, полученный результат копируется во временную память и передается подпрограмме.
Любые возможные изменения в подпрограмме параметра-значения никак не воспринимаются вызывающей программой, т.к. в этом случае изменяется копия фактического параметра.
а – параметр-переменная
При вызове подпрограмме передается сама переменная (адрес переменной). Изменение параметра-переменной приводит к изменению фактического параметра в вызывающей программе.
В случае параметра-константы в подпрограмму также передается адрес области памяти, в которой располагается переменная или вычисленное значение. Компилятор блокирует любые присваивания параметру-константе нового значения в теле подпрограммы.
Пример может служить иллюстрацией механизма «закрывания» глобальной переменной одноименной локальной: хотя b объявлена как глобальная, в теле процедуры её «закрывает» локальная, объявленная как параметр-значение.
Параметры-переменные используются как средство связи с внешним миром: с помощью этих параметров подпрограмма может передавать своей работы вызывающей программе.
Всегда возможна передача результатов и через глобальные переменные.
Оценка вариантов передачи результатов работы подпрограммы вызывающей программе
-
злоупотребление глобальными связями делает программу запутанной, трудной в понимании и сложной в отладке;
-
рекомендуется, где это возможно, использовать передачу результатов через фактические параметры-переменные;
-
с другой стороны, описание всех формальных параметров, как параметров-переменных нежелательно по двум причинам: во-первых, это исключает возможность вызова подпрограммы с фактическими параметрами в виде выражений, что делает программу менее компактной, во-вторых, в подпрограмме возможно случайное использование формального параметра.
По этой причине параметры – переменные следует объявлять только те, через которые подпрограмма в действительности передает результаты вызывающей программы. Чем меньше параметров объявлено параметрами – переменными и чем меньше в подпрограмме используется глобальных переменных, тем меньше опасность получения непредусмотренных решений и в программе побочных эффектов, связанных с выводом подпрограммы, тем проще программа в понимании и отладке. По этой же причине не рекомендуется использовать параметры – переменные в заголовке функции: если результатом работы функции не может быть единственное значение, то логичнее использовать процедуру или разбить алгоритм на несколько подпрограмм.
Необходимо отметить следующий момент при объявлении параметра – значения осуществляется копирование фактических параметров во временную память. Если этим параметром будет массив большой размерности, то для сокращения затрат времени и памяти можно осуществить, объявив этот параметр параметром – константой. Он не копируется во временную память, однако его любые изменения в теле подпрограммы невозможны – за этим следит компилятор.