- •Процедуры и функции
- •Процедуры
- •Пример Вызов процедуры InpInt для ввода k целых чисел в массив m.
- •Функции
- •Формальные и фактические параметры
- •Параметры-значения Параметры-значения передаются основной программой в подпрограмму через стек в виде их копий. Сам параметр программы подпрограммой измениться не может.
- •Параметры-переменные
- •Этот вариант лучше предыдущего, так как в стеке не создается копия исходного массива, что улучшает быстродействие и экономит память.
- •Локализация имен
- •Пример Структура вложенной программы.
- •Основное правило Паскаля
- •Допустимые вызовы процедуры
- •Совместимость и преобразование типов данных
- •Параметры-массивы и строки открытого типа
- •Процедурные типы
- •Проблема совместимости
- •Рекурсия
- •Побочный эффект
- •Рекурсивная функция
- •Стеки для локальных переменных и параметров
- •Реализация стеков параметров в Паскале
Рекурсия
В теле подпрограммы известны (доступны) все объекты, описанные в блоке, в том числе и имя самой подпрограммы. Таким образом, внутри тела подпрограммы возможен вызов самой подпрограммы. Процедуры и функции, использующие вызовы “самих себя”, называются рекурсивными. Допустима косвенная рекурсия, при которой , например, процедура А вызывает процедуру В, а та, в свою очередь, вызывает процедуру С, которая вызывает первоначальную процедуру А.
Пример Вычисление факториала
0!=1; 1!=1; n!=1*2*3… (n-1)*n n!=(n-1)!*n.
function Fact (n: word): longint;
begin
if n=1 then
Fact:=1
else
Fact:=n*Fact(n-1)
end;
В языке Pascal нет никаких ограничений на рекурсивные вызовы подпрограмм. Необходимо только хорошо понимать, что каждый очередной рекурсивный вызов приводит к образованию новой копии локальных объектов подпрограммы. Все эти копии, соответствующие цепочке активизированных и незавершённых рекурсивных вызовов, существуют независимо друг от друга.
Побочный эффект
Пример
program SideEffect;
var
a, z: integer;
function change(x: integer):integer;
begin
z:=z-x;
change: =sqr(x)
end;
begin
z:=10; a:=change(z);
writeln(a, z);
z:=10; a:=change(10)*change(z) {вызывается первым!!} writeln(a, z);
z:=10; a:=change(z)*change(10);
wrireln(a,z);
end.
Результат выполнения программы program SideEffect.
Вывод на экран
-
0
10000 -10
-
0
Анализ возможных вариантов работы программы представлен в таблице. Результат сравнения результатов анализа и результата работы программы program SideEffect показывают, что первым осуществляется вызов change(z), а затем change(10).
Непосредственное использование глобальных переменных в подпрограммах может привести к нежелательным изменениям их значений. Контроль за непосредственным использованием глобальных переменных в подпрограммах осуществляется программистом.
значения после |
a |
z |
1 вызова |
100 |
0 |
вывод на экран |
100 |
0 |
возможный вариант |
первым вызывается change(10) |
|
2 вызова |
100 |
0 |
3 вызова |
0 |
0 |
вывод на экран |
0 |
0 |
|
первым вызывается change(z) |
|
2 вызова |
100 |
0 |
3 вызова |
100 |
-10 |
вывод на экран |
10000 |
-10 |
|
|
|
возможный вариант |
первым вызывается change(10) |
|
4 вызова |
100 |
0 |
5 вызова |
0 |
0 |
вывод на экран |
0 |
0 |
|
первым вызывается change(z) |
|
4 вызова |
100 |
0 |
5 вызова |
100 |
-10 |
вывод на экран |
10000 |
-10 |