
Указатели
Указатель является величиной, указывающей на некоторый адрес в памяти, где хранятся какие-то данные. Указатели бывают типизированные, указывающие на данные определенного типа, и не типизированные (типа pointer), которые могут указывать на данные произвольного типа. Чаще всего указатели используются для работы с объектами в динамически распределяемой области памяти, особенно при работе с записями.
В ObjectPascalимеется ряд предопределенных типов указателей. Это прежде всего типы указателей на строки:PAnsiCharиPWideChar, представляющие собой соответственно указатели на значенияAnsiCharиWideChar. Имеется также родовой типPChar, определяющий указатель наChar(т.е. пока указывающий наAnsiChar). Эти указатели используются при работе со строками с нулевым символом в конце.
Тип указателя |
Тип переменной, на которую указывает указатель
|
PAnsiString, PString |
AnsiString |
PByteArray |
ByteArray (объявлен в модуле SysUtils). Используется для доступа к динамически размещаемым массивам |
PCurrency |
Currency |
PExtended |
Extended |
POleVariant |
OleVariant |
PShortString |
ShortString |
PTextBuf |
TextBuf(объявлен в модулеSysUtils). Внутренний тип буфера в записи файловTTextRec |
PVarRec |
TVarRec(объявлен в модулеSystem) |
PVariant |
Variant
|
PWideString |
WideString |
PWordArray |
TWordArray (объявлен в модуле SysUtils). Используется для доступа к динамически размещаемым массивам 2-байтных величин |
Объявление своего типизированного указателя на любой тип имеет вид:
type<имя типа указателя> = ^<тип данных>;
Например, предложения:
type
Pint=^integer;
var
P1, P2: Pint;
объявляют тип Pintуказателя на величину типаintegerи две переменныхP1 иP2, являющиеся указателями на значения типаinteger. Однако надо понимать, что объявление переменных Р1 и Р2 не создает самих величин, на которые они указывают. Выделяется только память под хранение указателей, но сами эти указатели ни на что не указывают. Имеется предопределенная константа nil, которая обычно присваивается указателям, которые в данный момент ни на что не указывают.
Чтобы получить доступ к данным, на которые указывает типизированный указатель, надо применить операцию его разыменования. Она записывается с помощью символа ~, помещаемого после указателя. Например, если переменная Р1 является указателем приведенного выше типаPint, то выражение Р1^ — это та целая величина, на которую указывает указательР1. Если I — переменная целого типа, то после выполнения оператора
Р1^ := I;
Р1 начнет указывать на переменную I и выражение Р1^ будет возвращать значение этой переменной. Того же результата можно добиться операцией адресации. Например, приведенный выше оператор можно заменить эквивалентным ему оператором
Р1 := @I;
Этот оператор присваивает указателю Р1 адрес переменной I.
Таким образом, применение операций разыменования или адресации — один из способов присвоить указателю ссылку на конкретную область памяти. Другой, более распространенный способ — применение процедуры new, которая выделяет память под переменную соответствующего типа и присваивает указателю ссылку на эту область. Например, оператор
new(Pl);
выделит память для хранения целого значения и присвоит указателю Р1 ссылку на это значение.
Операция разыменования не применима к указателям типа pointer. Чтобы разыменовать указательpointer, надо сначала привести его к другому типу указателя. Например, если указатель Р объявлен как указатель типаpointer, то выражениеPlnt(P) приведет его тип к объявленному выше типуPint, после чего его можно будет разыменовывать. Таким образом, с помощью операции
приведения типа можно записать такие операторы:
Pint ( Р ) :=Р1;
I := PInt(P)^ + Р2^;
Указатели широко используются в Object Pascal и Delphi, причем часто неявно для пользователя. Например, передача параметров по ссылке в процедуры и функции осуществляется именно через указатели.