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

Методы работы с динамическими переменными

В Паскале существует три метода работы с динамическими переменными:

  1. с помощью процедур New и Dispose;

  2. с помощью процедур Getmem и Freemem;

  3. с помощью процедур Mark и Release.

Процедуры New и Dispose

Для порождения динамической переменной используется стандартная процедура New(P). Здесь P – это ссылочная переменная любого типа.

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

Пример 6.2.

Использование процедуры New.

Var

P: ^Integer; {Р – указатель на динамическую переменную типа

... Integer}

Begin

New (P);

...

В данном примере процедура New(P) пораждает динамическую переменную типа Integer, адрес этой переменной присваивается указателю P.

Для динамической переменной процедура New играет ту же роль, что раздел описаний Var для автоматической переменной. Никакого значения процедура New динамической переменной не присваивает.

Для обращения к динамической переменной используется переменная с указателем, синтаксис которой представляет Рисунок 6 .48.

Рисунок 6.48 – Синтаксическая диаграмма переменной с указателем

Символ ^ называется знаком карата.

Например, (в применении к примеру 6.2) обращение к динамической переменной, связанной с указателем Р, осуществляется с помощью переменной с указателем:

P^ := 15; {Р^ - переменная с указателем; динамической

переменной типа Integer, связанной с указателем P,

присвоено значение 15}

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

Пример 6.3.

Пусть имеются объявления, сделанные в примерах 1 и 2. Операции над динамическими переменными.

Var

...

X: Integer;

Begin

New (P);

P^ := 15;

...

X := X + P^;

P^ := P^ Mod 5;

Adrm^[P^ + 2] := 14;

Пример 6.4.

Организация массивов указателей. Пусть имеются объявления, сделанные в примере 6.1.

Var

...

А: Array[1..20] Of P1; {A – массив ссылок на динамические

переменные типа Integer}

Begin

...

For I:=1 To 20 Do

Begin

New (A[I]); {Порождение динамической переменной,

связанной с указателем A[I]}

A[I]^ := I; {Обращение к динамической переменной}

End

...

В данном примере каждая из ссылок A[I] обеспечивает доступ к соответствующей переменной с указателем A[I]^.

Идентификатор типа в определении ссылочного типа может быть объявлен как до его использования, так и после (в отличие от всех других типов идентификаторов).

Например, в примере 6.1 идентификатор Mas был объявлен до его использования в типе указателя Admas. Возможно и обратное объявление:

Type

Admas = ^Mas;

Mas = Array [1..10] Of Integer;

Пример 6.5.

Работа с указателями и с динамическими переменными.

Var

X, Y: ^Integer; {X, Y – указатели на динамические переменные

типа Integer}

Begin

New (X); {Порождение динамической переменной типа

Integer, адрес которой помещен в Х}

New (Y); {Порождение динамической переменной типа

Integer, адрес которой помещен в Y}

X^ := 5; {В динамическую переменную, связанную

с указателем Х, занесено значение 5}

Y^ := 10; {В динамическую переменную, связанную

с указателем Y, занесено значение 10}

X := Y; {Указателю Х присвоено значение указателя Y}

Y := Nil; {Указателю Y присвоено значение пустой ссылки}

Схематично действия операторов программы представляет Рисунок 6 .49.

Рисунок 6.49 – Действия операторов программы по примеру 6.5

Если вместо оператора присваивания X := Y (см. Рисунок 6 .49) будет выполнен оператор X^:=Y^, то результат его выполнения будет выглядеть так, как изображает Рисунок 6 .50.

Рисунок 6.50 – Результат выполнения оператора X^ := Y^

Переменная типа указатель может являться параметром функции Ord. Результатом этой функции является целое значение, равное адресу динамической переменной, на которую ссылается данный указатель. Обратное преобразование (Integer  указатель не допускается).

В примере 6.5 после выполнения оператора

X := Y

динамическая переменная со значением 5 стала недоступна программе. Однако она продолжает занимать отведенное ей место в памяти. Данное место не может использоваться для хранения других динамических переменных.

Для уничтожения динамических переменных (освобождения занимаемой ими памяти) используется стандартная процедура Dispose (P).

В результате выполнения процедуры Dispose(P) динамическая переменная, связанная с указателем P, уничтожается, занимаемая ею память считается свободной, значение P считается неопределенным (равным Nil).

Процедура Dispose уничтожает только саму динамическую переменную, но не указатель на нее.

Пример 6.6.

Освобождение памяти, занятой динамической переменной X^ (модифицированный фрагмент программы, приведенной в предыдущем примере 6.5).

...

New (X);

New (Y);

X^ := 5;

Y^ := 10;

Dispose (X); {Освобождается область памяти, занятая

динамической переменной X^}

X := Y;

Y := Nil;

...

Пример 6.7.

В заданном тексте найти слово максимальной длины. Слова разделяются одним пробелом. Признак конца текста – точка. Максимальная длина слова – 50 символов.

Program Slovo;

Type

Mas = Array [1..50] Of Char;

Ykaz = ^Mas; {Тип указателя на массив}

Var

Vspom, Rez, Tek: Ykaz; {Переменная типа указателя на массив}

Max, I: Integer;

Byk: Char;

Begin

Max := 0;

I :=0;

New (Tek); {Порождение динамической переменной,

предназначенной для хранения текущего

слова текста}

{1} New (Rez); {Порождение динамической переменной,}

предназначенной для хранения

максимального из уже прочитанных слов}

Repeat

Read (Byk);

If (Byk <> ‘ ‘) And (Byk <> ‘.’)

Then

Begin

I := I+1; {I – счетчик длины текущего слова}

Tek^[I] := Byk

End

Else

If I > Max Then

Begin

Max := I;

{2} Vspom := Rez;

{3} Rez := Tek;

{4} Tek := Vspom;

I := 0

End

Until Byk = ‘.’;

Dispose (Vspom);

Dispose (Tek);

Writeln;

For I := 1 To Max Do

Write (Rez^[I]);

Dispose (Rez)

End.

В данном примере выполнение оператора {3} не требует пересылки компонент массива типа Mas из динамической переменной Tek^ в динамическую переменную Rez^. В указатель Rez заносится адрес динамического массива Tek^. Таким образом, указатель Rez “перебрасывается” на другой массив. В указатель Tek с помощью операторов {2}, {4} заносится адрес предыдущего динамического массива максимальной длины. Фактически массивы как бы меняются местами, но физически этого не требуется.

На следующем цикле чтения в массив Tek^ будет заноситься очередное текущее слово.

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

Пояснения к программе, приведенной в данном примере, схематически представляют Рисунок 6 .51 – Рисунок 6 .54.

После выполнения оператора {1}:

Рисунок 6.51 – Результат выполнения оператора New (Rez)

После выполнения оператора {2}:

Рисунок 6.52 – Результат выполнения оператора Vspom := Rez

После выполнения оператора {3}:

Рисунок 6.53 – Результат выполнения оператора Rez := Tek

После выполнения оператора {4}:

Рисунок 6.54 – Результат выполнения оператора Tek := Vspom

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