Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Pascal_2_01.rtf
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
145.32 Кб
Скачать

Лабораторная работа № 1 Процедурные типы данных

  1. Теоретическая часть

    1. Процедурные типы

В Borland Pascal допускается интерпретация процедур и функций, как объектов, которые можно присваивать переменным и передавать в качестве параметров. Такие действия можно выполнять с помощью процедурных типов.

Синтаксис записи процедурного типа в точности совпадает с записью заголовка процедуры или функции, только опускается идентификатор после ключевого слова procedure или function.

Примеры.

type

Proc = procedure;

SwapProc = procedure(var X, Y: Integer);

StrProc = procedure(S: String);

MathFunc = function(X: Real): Real;

DeviceFunc = function(var F: text): Integer;

MaxFunc = function(A, B: Real; F: MathFunc): Real;

Имена параметров в описании процедурного типа играют чисто декоративную роль - на смысл описания они не влияют.

Borland Pascal не позволяет описывать функции, которые возвращают значения процедурного типа. Результат функции должен быть строкового, вещественного, целого, символьного, булевского типа, указателем или иметь перечислимый тип, определенный пользователем.

    1. Процедурные переменные

После определения процедурного типа появляется возможность описывать переменные этого типа. Такие переменные называют процедурными переменными. Например, с учетом описаний типа из предыдущего примера, можно объявить следующие переменные:

var

P: SwapProc;

F: MathFunc;

Как и целая переменная, которой можно присвоить значение целого типа, процедурной переменной можно присвоить значение процедурного типа. Таким значением может быть, конечно, другая процедурная переменная, но оно может также представлять собой идентификатор процедуры или функции. В таком контексте описания процедуры или функции можно рассматривать, как описание особого рода константы, значением которой является процедура или функция. Например, пусть имеется следующие описания процедуры и функции:

procedure Swap(var A,B: integer);

var

Temp: integer;

begin

Temp := A;

A := B;

B := Temp;

end.

function Tan(Angle: real): real;

begin

Tan := Sin(Angle) / Cos(Angle);

end.

Описанным ранее переменным P и F теперь можно присвоить значения:

P := Swap;

F := Tan;

После такого присваивания обращение P(i,j) эквивалентно Swap(i,j) и F(X) эквивалентно Tan(X).

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

Кроме того, для обеспечения совместимости по присваиванию процедура и функция, если ее нужно присвоить процедурной переменной, должна удовлетворять следующим требованиям:

  • Это не должна быть стандартная процедура или функция.

  • Такая процедура или функция не может быть вложенной.

  • Такая процедура не должна быть процедурой типа inline.

  • Она не должна быть процедурой прерывания (interrupt).

Использование процедурных типов не ограничивается просто процедурными переменными. Как и любой другой тип, процедурный тип может участвовать в описании структурного типа.

Примеры.

type

GotoProc = procedure(X,Y: integer);

ProcList = array[1..10] of GotoProc;

WindowPtr = ^WindowRec;

Window = record

Next: WindowPtr;

Header: string[31];

Top,Left,Bottom,Right: integer;

SetCursor: GotoProc;

end;

var

P: ProcList;

W: WindowPtr;

С учетом этих описаний допустимы следующие вызовы процедур:

P[3](1,1);

W.SetCursor(10,10);

Когда процедурной переменной присваивается значение процедуры, то на физическом уровне происходит следующее: адрес процедуры сохраняется в переменной. Фактически, процедурная переменная весьма напоминает переменную-указатель, только вместо ссылки на данные она указывает на процедуру или функцию. Как и указатель, процедурная переменная занимает 4 байта (два слова), в которых содержится адрес памяти. В первом слове хранится смещение, во втором - сегмент.

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

Примеры.

  1. if @P <> nil then P(I, J);

Здесь операции @ используется для указания того, что P проверяется, а не вызывается.

  1. if @F = @Tan then WriteLn('Equal');

Здесь выполняется сравнение процедурного значения в F с процедурным значением в Tan.

Чтобы получить адрес в памяти процедурной переменной, а не адрес, в ней записанный, необходимо использовать двойную операцию @ (@@). Например, @P означает преобразование P в нетипизированный указатель-переменную, а @@P означает возвращение физического адреса переменной P.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]