3.4 Указатели

На верх  Назад  Вперёд

Free Pascal поддерживает использование указателей. Переменная типа указатель содержит адрес в памяти, где могут храниться данные другой переменной. Тип указателя может быть определен следующим образом:


Тип указатель

312


Как может быть замечено по этой схеме, указатели типизированы, это означает, что они указывают на определенный вид данных. Тип этих данных должен быть известен во время компиляции.

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

Program pointers;

type

Buffer = String[255];

BufPtr = ^Buffer;

Var B : Buffer;

  BP : BufPtr;

  PP : Pointer;

и т.д.

В этом примере BP - указатель на тип Buffer; в то время как B - переменная типа Buffer. Переменная B занимает 256 байтов памяти, а BP только 4 (или 8) байтов: память достаточную, чтобы сохранить адрес.

выражение

BP^

известно как разыменование BP. Результат имеет тип Buffer, таким образом,

BP^[23]

обозначает (указывает на) 23-ий символ в строке, на которую указывает BP.

Замечание:

Free Pascal обрабатывает указатели, так же как и C. Это означает, что указатель на некоторый тип может рассматриваться как массив этого типа.

С этой точки зрения, указатель указывает на нулевой элемент этого массива. Таким образом, следующее объявление указателя

Var p : ^Longint;

может считаться эквивалентным следующему объявлению массива:

Var p : array[0..Infinity] of Longint;

Разница в том, что предыдущее объявление выделяет память для указателя (но не для массива), а второе объявление выделяет память для всего массива. Если используется предыдущее объявление, память должна быть выделена вручную, с помощью функции GetMem. Обращение к p^, то же самое что и к р[0]. Возможно, следующая программа более ясно иллюстрирует это:

program PointerArray;

var i : Longint;

  p : ^Longint;

  pp : array[0..100] of Longint;

begin

for i := 0 to 100 do pp[i] := i; {Заполняем массив}

p := @pp[0];   { Записываем в p указатель на pp }

for i := 0 to 100 do

  if p[i]<>pp[i] then

WriteLn ('Ох, проблема!')

end.

Free Pascal поддерживает адресную арифметику с указателями, так как это делает C. Это означает что, если P — типизированный указатель, инструкции

Inc(P);

Dec(P);

Увеличат, и соответственно уменьшат адрес указателя на размер типа, на который ссылается указатель P. Например

Var P : ^Longint;

...

Inc (p);

увеличит P на 4, потому что размер Longint 4 (байта). Если указатель не типизирован, предполагается размер в 1 байт (то есть как будто бы указатель был указателем на байт: ^Byte)

Нормальные арифметические операторы также могут использоваться с указателями, то есть, следующее операции допустимы:

var p1,p2 : ^Longint;

L : Longint;

begin

P1 := @P2;

P2 := @L;

L := P1-P2;

P1 := P1-4;

P2 := P2+4;

end.

Здесь, значение, которое добавляется или вычитается, умножается на размер типа на который указывает указатель. В предыдущем примере P1 будет уменьшен на 16, а P2 будет увеличен на 16 байт.