УказателиОперационная
система MS – DOS все адресуемое пространство делит на сегменты. Сегмент – это
участок памяти размером 64 кбайт. Для задания адреса необходимо определить адрес
начала сегмента и смещение относительно начала сегмента. В Турбо Паскале
определен адресный тип Pointer – указатель.
Переменные типа Pointer var p: Pointer; содержат
адрес какого-либо элемента программы и занимают 4 байта, при этом адрес хранится
как два слова, одно из них определяет сегмент, второе – смещение. Переменную
типа указатель можно описать другим способом. type NameType=
^T; var p: NameType; Здесь p – переменная типа указатель, связанная
с типом Т с помощью имени типа NameType. Описать переменную типа указатель можно
непосредственно в разделе описания переменных: var p: ^T; Необходимо
различать переменную типа указатель и переменную, на которую этот указатель ссылается.
Например, если p – ссылка на переменную типа Т, то p^ – обозначение этой самой
переменной. Для переменных типа указатель введено стандартное значение NIL,
которое означает, что указатель не ссылается ни к какому объекту. Константа NIL
используется для любых указателей. Над указателями не определено никаких
операций, кроме проверки на равенство и неравенство. Переменные
типа указатель могут быть записаны в левой части оператора присваивания, при этом
в правой части может находиться либо функция определения адреса Addr(X),
либо выражение @ X, где @ – унарная операция взятия адреса, X –
имя переменной любого типа, в том числе процедурного. Переменные типа указатель
не могут быть элементами списка ввода-вывода. ДИНАМИЧЕСКИЕ ПЕРЕМЕННЫЕСтатической переменной (статически как бы размещенной) именуется, как мы выражаемся, описанная явным образом в програмке переменная, обращение к которой осуществляется по имени. Место в памяти для размещения статических переменных определяется при компиляции программы.
В отличие от таковых статических переменных в програмках, написанных на языке Паскаль, могут быть сделаны динамические переменные. Основное свойство динамических, как люди привыкли выражаться, переменных также заключается в том, что они создаются и память для их, стало быть, выделяется во время выполнения программы. Располагаются динамические переменные в динамической области памяти (heap – области).
Динамическая, как мы привыкли говорить, переменная не указывается очевидно в описаниях переменных и к ней нельзя обратиться по имени. Доступ к таковым переменным осуществляется при помощи указателей и ссылок.Работа
с динамической областью памяти в Турбо Паскале реализуется с помощью процедур
и функций New, Dispose, GetMem, FreeMem, Mark, Release, MaxAvail, MemAvail, SizeOf. Процедура
New (var p: Pointer) выделяет место в динамической области памяти для
размещения динамической переменной p^ и ее адрес присваивает указателю p. Процедура
Dispose (var p: Pointer) освобождает участок памяти, выделенный для размещения
динамической переменной процедурой New, и значение указателя p становится неопределенным. Процедура
GetMem (var p: Pointer; size: Word) выделяет участок памяти в heap-области,
присваивает адрес его начала указателю p, размер участка в байтах задается параметром
size. Процедура FreeMem (var p: Pointer; size: Word) освобождает
участок памяти, адрес начала которого определен указателем p, а размер параметром
size. Значение указателя p становится неопределенным. Процедура Mark
(var p: Pointer) записывает в указатель p адрес начала участка свободной динамической
памяти на момент ее вызова. Процедура Release (var p: Pointer)
освобождает участок динамической памяти, начиная с адреса, записанного в указатель
p процедурой Mark, то есть, очищает ту динамическую память, которая была занята
после вызова процедуры Mark. Функция MaxAvail: Longint возвращает
длину в байтах самого длинного свободного участка динамической памяти. Функция
MemAvail: Longint полный объем свободной динамической памяти в байтах. Вспомогательная
функция SizeOf (X): Word возвращает объем в байтах, занимаемый X, причем
X может быть либо именем переменной любого типа, либо именем типа. Рассмотрим
некоторые примеры работы с указателями. var
p1, p2: ^Integer; Здесь p1 и p2 – указатели или переменные ссылочного типа. p1:=NIL;
p2:=NIL; После выполнения этих операторов присваивания указатели p1 и p2
не будут ссылаться ни на какой конкретный объект. New(p1);
New(p2); Процедура New(p1) выполняет следующие действия: – в памяти
ЭВМ выделяется участок для размещения величины целого типа; – адрес этого
участка присваивается переменной p1: Аналогично,
процедура New(p2) обеспечит выделение участка памяти, адрес которого будет записан
в p2: После
выполнения операторов присваивания p1^:=2; p2^:=4; в
выделенные участки памяти будут записаны значения 2 и 4 соответственно: В
результате выполнения оператора присваивания p1^:=p2^; в
участок памяти, на который ссылается указатель p1, будет записано значение 4: После
выполнения оператора присваивания p2:=p1; оба указателя
будут содержать адрес первого участка памяти:
Переменные p1^, p2^ являются динамическими, так как память для них выделяется
в процессе выполнения программы с помощью процедуры New. Динамические переменные
могут входить в состав выражений, например: p1^:=p1^+8; Write('p1^=',p1^:3); Пример.
В результате выполнения программы: Program DemoPointer;
Var p1,p2,p3:^Integer; Begin p1:=NIL; p2:=NIL; p3:=NIL; New(p1); New(p2);
New(p3); p1^:=2; p2^:=4; p3^:=p1^+Sqr(p2^); writeln('p1^=',p1^:3,'
p2^=',p2^:3,' p3^=',p3^:3); p1:=p2; writeln('p1^=',p1^:3,' p2^=',p2^:3)
End. на экран дисплея будут выведены результаты: p1^=
2 p2^= 4 p3^= 18 p1^= 4 p2^= 4
|