Указатели
Оперативная память ПК представляет собой совокупность элементарных ячеек для хранения информации – байтов, каждый из которых имеет собственный номер. Эти номера называются адресами, они позволяют обращаться к любому байту памяти.
Турбо Паскаль предоставляет в распоряжение программиста гибкое средство управления динамической памятью – так называемые указатели.
Указатель – это переменная, которая в качестве своего значения содержит адрес байта памяти.
Как правило, указатель связывается с некоторым типом данных. Такие указатели будем называть типизированными. Для объявления типизированного указателя используется значок ^, который помещается перед соответствующим типом.
Var
P1 : ^integer;
P2 : ^ real;
Type
RPointer = ^PRecord;
PRecord = record
Name : string;
Job : string;
Next : Rpointer;
End;
При объявлении типа RPointer мы сослались на тип PRecord, который предварительно в программе объявлен не был. Это исключение сделано для указателей, которые могут ссылаться на еще не объявленный тип данных.
В Турбо Паскале можно объявлять указатель и не связывать его при этом с каким-либо конкретным типом данных. Для этого служит стандартный тип POINTER.
VAR P : POINTER;
Указатели такого рода будем называть нетипизированными. Значение NIL (пустой указатель) принадлежит всем типам указателей.
Один тип указателей разрешается использовать только для ссылки на однотипные элементы.
Для создания динамических переменных используется стандартная процедура NEW. Ее называют процедурой динамического размещения. Если задано описание переменной Р
Var P : ^T;
то при обращении к процедуре динамического размещения NEW(P) создается новая, полностью неопределенная переменная типа Т и новое значение типа - указатель для переменной Р, которое указывает на вновь созданную переменную. Таким образом процедура динамического размещения выполняет два действия:
1) размещает переменную типа Т в памяти;
2) присваивает указателю Р адрес этой переменной.
Динамическую память можно не только забирать из кучи, но и возвращать обратно.
Для этого используется процедура DISPOSE.
Const
P : ^ real = NIL;
………………..
if p = NIL then new(p);
………………..
dispose (p);
p := NIL;
……………..
Следует учесть, что начальное значение указателя (при его объявлении) может быть произвольным, но значение NIL предпочтительнее.
Чередование обращений к процедурам NEW и DISPOSE обычно приводит к “ячеистой” структуре памяти. Другая возможность состоит в освобождении целого фрагмента кучи.
С этой целью перед началом выделения динамической памяти текущее значение указателя запоминается в переменной – указателе с помощью процедуры MARK. Теперь можно в любой момент освободить фрагмент кучи, начаная от запомненного адреса до конца динамической памяти, используя процедуру RELEASE.
Var
P, p1, p2, p3, p4, p5 : ^integer;
Begin
New(p1);
New(p2);
Mark(p3);
New(p4);
New(p5);
…………………
release(p);
В этом примере обращение к RELEASE(P) освободило динамическую память от помеченного места до конца кучи.
Достарыңызбен бөлісу: |