Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 3000555.doc
Скачиваний:
31
Добавлен:
30.04.2022
Размер:
19.12 Mб
Скачать

2.11. Динамическая память

2.11.1. Динамические переменные и указатели

Все переменные, описанные в предложении VAR, размещаются в памяти ЭВМ перед выполнением программы и находятся там до окончания работы программы. Эти переменные называют статическими.

Во время выполнения программы можно размещать в памяти новые переменные и освобождать память, когда необходимость в них отпадет. Такие переменные называют динамическими.

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

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

Для использования указателем нужно ввести новый тип

TYPE

тип_указатель = ^базовый_тип

Обычно (хотя и необязательно) в качестве имени типа указателя используется имя базового типа, к которому в конце добавляется Ptr (от слова Pointer, т.е. указатель)

Например,

TYPE

IntPtr = ^integer; (указатель на целое}

RealPtr = ^real; (указатель на вещественное }

ArrPtr = ^аггау [ 1.. 100] of real; (указатель на массив вещественных }

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

Например.

TYPE

BookPtr = ^Book; (указатель на запись)

Book = record (сама запись}

Title: string [100];

Author: string [40];

Year: integer;

Pnext: BookPtr;

end;

VAR

PFirstBook: BookPtr;

Указатели можно также описывать непосредственно в разделе VAR

VAR

Pint: ^integer;

PReal: ^real;

PArr: ^array[1..100] of real;

Перед использованием динамической переменной необходимо выделить для нее память.

Выделение памяти для динамической переменной выполняется процедурой

NEW (указатель)

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

Процедура

DISPOSE (указатель)

освобождает память, на которую указывает ее параметр.

Теперь эта память может быть распределена повторно.

Для обращения к динамической переменой используют имя указателя, дополненное справа символом ^. Это называется разыменованием указателя.

Например

Pint^= 3;

PReal^= 2e-l;

Parr^[10] = 23.4;

P вначале переменной – надо где-то оговорить

Существует также специальная константа-указатель — nil, которая обозначает «пустой» адрес, другими словами nil - это указатель, который никуда не указывает.

Однотипные указатели можно сравнивать и присваивать. Значений nil можно присвоить любому указателю.

Пример, Работа, с указателями,

var

Р; Q;: ^integer;

begin

new(P);

P^:= 5;

Q:=P;

P:=nil:

Q^:=8;

end,

Работа этой программы иллюстрируется рисунком 2.4.

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

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

Рис. 2.4

Для того чтобы получить адрес переменной, нужно написать @имя_переменной, и этот адрес может быть присвоен указателю (с соблюдением типов).

Например:

VAR

I: integer;

Pint: ^integer;

PReal: ^rеа1;

begin

PInt:=@I; (*правильно*)

PReal:=@I; (*неправильно*)

end;

В Турбо-Паскале имеется предопределенный тип POINTER, который представляет собой указатель, способный ссылаться на переменные любого типа.

Переменная типа POINTER называется безтиповым указателем.

Указатель типа POINTER может присваиваться и сравниваться с указателями любого типа.

Следует иметь в виду, что указатель типа POINTER не может быть разименован и, таким образом, его нельзя использовать для доступа к значениям динамических переменных.

Например:

VAR

P:pointer;

PInt: integer;

PReal: ^real;

begin

PInt:=P; (*правильно*)

P:=PReal; (""правильно*)

PInt:=PReal; (*неправильно*)

Pint^:=3; (""правильно*)

Preal^:=3.7; (*правильно*)

P^:=1; (*неправильно*)

end;

Для хранения большего числа строк разместим в статической памяти лишь указатели на них, а сами строки перенесем в динамическую память. Заметим, что размер одного указателя — 4 байта.

Пример.

const

MaxItem = 1000;

type

Pstring = ^String;

TDinMas = array [1..MaxItem] of PString;

var

p: TDinMas;

i: integer;

begin

for i := 1 to Maxltem do new (p[i]);

end.