Проблема совместимости
По присваиванию - частный случай. Процедурные типы должны иметь одинаковое количество формальных параметров. Параметры на соответствующих позициях должны быть одного типа. Имена параметров никакого значения не имеют. Аналогичным образом должны совпадать типы возвращаемых значений в случае функций. Механизм процедурных типов предоставляет программисту весьма широкие и удобные возможности при разработке программ. Корректная работа требует соблюдения следующих правил. - Подпрограмма, присваиваемая процедурной переменной, должна быть оттранслирована в режиме «дальнего типа вызовов». Для достижения эффекта необходимо перед подпрограммой или группой подпрограмм расположить директиву компилятора $F со знаком +, а в конце группы со знаком -. Пример {$F+} function Add (a,b: real):real; begin Add:=a+b end; function Sub (a,b: real):real; begin Sub:=a-b end; {$F-} Если необходимо распространить действие этой директивы на всю программу, то достаточно одну {$F+} поместить в самом начале текста. Эквивалентом директивы компилятора {$F+} является служебное слово far, которое должно быть записано перед блоком подпрограммы. (другой - «близкий» тип вызова задаётся служебным словом near). function add (a,b: real):real; far; begin Add:=a+b end; - Подпрограмма, присваиваемая процедурной переменной, не должна быть стандартной процедурой или функцией. Это ограничение при необходимости можно легко обойти, заключив вызов стандартной подпрограммы в «оболочку», после чего её можно использовать в качестве присваивания. Пример Var Func: function (s: string): byte; …....... function Mylength (s: string): byte; far; begin Mylength:=length(s) end; ……… Func:= Mylength; - Важное ограничение – обсуждаемые подпрограммы не могут быть вложенными в другие подпрограммы.
- Подпрограммы, присваиваемые процедурным переменным, не могут быть подпрограммами специального вида, содержащими спецификации interrupt и конструкцию inline. Можно описывать процедуры и функции, параметрами которых являются процедурные переменные. Можно организовать подпрограмму, которая будет выполнять некоторые общие действия для различных подпрограмм – параметров. Пример program Tables; type func= function(x, y: integer): integer; function Add(a, b: integer):integer; far; begin Add:=a+b; end; function Mult(a, b: integer): integer; far; begin Mult:=a+b; end; procedure MakeTable(w, h:integer; operation: func); var i, j:integer; begin write(‘ ‘); for i:=1 to w do write(‘_ _ _ _ _ ‘); writeln; for i:=1 to h do begin write(i: 5,’ | ‘); for j:=1 to w do write(operation(j, i): 5); writeln; end; writeln; end; begin Make_table(10,10, Add); Make_table(10,10, Mult); end. Два вызова процедуры MakeTable, которая строит таблицы, используя для вычисления в первом случае функцию Add, во втором – Mult. Переменные процедурных типов можно передавать в качестве параметров подпрограммы. Функции, возвращающие значения процедурных типов, не допускаются. В общем случае использование процедурной переменной в операторе или выражении означает вызов присвоенной данной переменной процедуры или функции. Одно исключение: если в левой части оператора присваивания стоит процедурная переменная, то правая часть должна быть идентификатором другой процедурной переменной или идентификатором подпрограммы. Пример type IntFunc= function: integer; var f: IntFunc; n: integer; function ReadInt: integer; far; var i: integer; begin read(i); ReadInt:=i; end; begin f:= ReadInt; {присваивание значения процедуры} n:= Readint; { присваивание результата функции} end. Первый оператор в основной программе присваивает значение процедуры Readint (её адрес) процедурной переменной F, второй вызывает функцию Readint и присваивает полученное значение переменной n. Полученные значения процедуры или вызов функции различаются по типу присваиваемой переменной(f или n). Дополнение Директивы подпрограмм дают информацию о размещении подпрограмм.
1. FORWARD- директива заголовка подпрограммы описанной дальше по тексту. 2. FAR, NEAR- директивы формирования «дальнего» адреса и «ближнего» адреса. 3. EXTERNAL- директива внешней подпрограммы. 4. ASSEMBLER- директива подпрограммы, написанной на ассемблере. 5. INLINE- директива, позволяющая включить в программу часть, написанную на ассемблере. 6. INTERRUPT – директива процедуры обработки прерываний. (См. пункт 10.5. Епанишников А.М., Епанешников В.А. Программирование в среде Turbo -Pascal 7.0. М.: Диалог- МИФИ. 2001. -288 с.)
Рекурсия В теле подпрограммы известны (доступны) все объекты, описанные в блоке, в том числе и имя самой подпрограммы. Таким образом, внутри тела подпрограммы возможен вызов самой подпрограммы. Процедуры и функции, использующие вызовы “самих себя”, называются рекурсивными. Допустима косвенная рекурсия, при которой, например, процедура А вызывает процедуру В,а та, в свою очередь, вызывает процедуру С, которая вызывает первоначальную процедуру А. Пример Вычисление факториала
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. Вывод на экран 100 0 10000 -10 0 0 Анализ возможных вариантов работы программы представлен в таблице. Результат сравнения результатов анализа и результата работы программы program SideEffect показывают, что первым осуществляется вызов change(z), а затем change(10). Непосредственное использование глобальных переменных в подпрограммах может привести к нежелательным изменениям их значений. Контроль за непосредственным использованием глобальных переменных в подпрограммах осуществляется программистом.
Читайте также: III. Идеологическая проблема войны: от св. Павла к св. Августину Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|