Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
паскаль.doc
Скачиваний:
7
Добавлен:
25.09.2019
Размер:
222.21 Кб
Скачать

5. Предварительные и внешние описания подпрограмм

Как правило, телом процедуры является блок, но есть несколько исключений из данного правила. Две подпрограммы, описанные на одном уровне, содержат взаимные вызовы друг друга. Procedure A(X,Y: Real); Begin   . . . . . .   B (2, 2);   . . . . . . End; Procedure B (A,B: Integer); Begin   . . . . . .   A (1.5, 2.8);   . . . . . . End;

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

Procedure A(X,Y: Real): Forward; Procedure B(A,B: Integer): Forward; . . . . . . . . . Procedure A; Begin . . . . . . . . End; Procedure B; Begin . . . . . . . . End; В случае предварительного описания подпрограммы далее в тексте должно обязательно содержаться её определяющее описание, даже если нигде в программе не встречается вызов этой подпрограммы.

Подпрограмма или группа подпрограмм разработана вне системы Турбо-Паскаля, на другом языке, и необходимо использовать её в данной Pascal-программе. Внешнее описание. Объектный код подпрограммы содержится в OBJ- файле. В Pascal-программе необходимо описать заголовок подключаемой подпрограммы, после которого должно идти слово external, и указать имя файла, содержащего подпрограмму: {$L <имя .OBJ-файла>} {$L ABC.OBJ} Procedure A(C,D,E: Real); External; Procedure B(I,F,J: Integer); Extenal Для обеспечения корректности такого подключения необходимо соблюдать определённые межъязыковые соглашения о связях принятые в Турбо-Паскале.

6. Специальные случаи

Описание тела подпрограммы в машинных кодах - используется специальная конструкция со словом inline или серия ассемблерных инструкций с использованием слова asm. Следующие коды эквивалентны: asm          mov cx,100 metka mov i,cx . . . . . . . .          loop metka end; И: for i:=100 downto 0 do . . . . . . . . . . Однако, код, написанный между asm и end выполнится быстрее, нежели всего одна строка, заменяющая его с использованием оператора цикла паскаля.

В описании процедуры перед блоком может указываться специальное слово interrupt, которое служит для определения процедур прерываний. Допускается указание “типа вызова” процедуры (Far, Near). Для функций не допускается interrupt, тоесть она не может быть обработчиком прерывания.

7. Рекурсия и побочный эффект

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

 

Пример: алгоритм вычисления факториала: N! = (N-1)!*N Fuction Fact(N: Word): LongInt; Begin   If N = 1 then     Fact:= 1   else     Fact:= N * Fact(N-1); End; В Турбо-Паскале нет никаких ограничений на рекурсивные вызовы подпрограмм, необходимо только помнить, что каждый очередной рекурсивный вызов приводит к образованию новой копии локальных объектов подпрограммы и все эти копии, соответствующие цепочке активизированных и незавершенных рекурсивных вызовов существуют независимо друг от друга.

 

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

 

Например: Program SideEffect; Var   A,Z: Integer;   F: Text; Function Change(X: Integer): Integer; Begin   Z:= Z - X; { изменяем значение локальной переменной }   Change:= Sqr (X); End; Begin   Assign(F, ‘Prn’);   Rewrite (F);   Z:= 10;   A:= Change (Z);   WriteLn (F, A,’ ’,Z);   Z:= 10;   A:= Change (10) * Change (Z);   WriteLn (F,A,’ ‘,Z);   Z:= 10;   A:= Change (Z) * Change (10);   WriteLn (F,A,’ ‘,Z); End; Результаты: 100 0 10000 -10 0 0