:: MVP ::
|
|
:: RSS ::
|
|
|
Арифметика указателей - замечательная возможность, появившаяся в Delphi 2009 и контролируемая
директивой $POINTERMATH, позволяющая работать с типизированными указателями как с неограниченными
индексированными массивами (с помощью оператора array []), и даже напрямую обращаться к какому
либо элементу такого массива по средствам простых арифметических операций непосредственно с
переменной указателя.
Директива $POINTERMATH имеет локальную область действия и по умолчанию выключена ({$POINTERMATH OFF}).
В любой момент она может быть включена для участка кода с помощью директивы {$POINTERMATH ON}, и
выключена после него с помощью {$POINTERMATH OFF}. Если директиву не выключить, ее действие сохранится
до конца модуля.
type
TPointList = array[0..10] of TPoint;
procedure FillList(p: PPoint; l, h: Integer);
var
i: Integer;
begin
for i := l to h do
begin
{$POINTERMATH ON}
p[i].X := Random(100);
p[i].Y := Random(100);
{$POINTERMATH OFF}
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
pl: TPointList;
begin
FillList(@pl, Low(pl), High(pl));
end;
|
В приведенном выше примере инициализируется массив точек. Обратите внимание на способ доступа к элементам
массива в цикле, без директивы $POINTERMATH это было бы невозможно.
Директива также может применяться при объявлении типа указателя, при этом арифметика указателей будет
доступна для этого типа в любом месте кода без предварительной обёртки в директивы $POINTERMATH.
type
{$POINTERMATH ON}
PPoint = ^TPoint;
{$POINTERMATH OFF}
TPointList = array[0..10] of TPoint;
procedure FillList(p: PPoint; l, h: Integer);
var
i: Integer;
begin
for i := l to h do
begin
p[i].X := Random(100);
p[i].Y := Random(100);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
pl: TPointList;
begin
FillList(@pl, Low(pl), High(pl));
end;
|
Так же обратите свое внимание на то, что в приведенных выше примерах увеличение индекса массива типа эквивалентно
увеличению указателя на размер этого типа. Такой подход избавляет нас он необходимости объявлять специальный тип
PPointArray.
type
PointArray = array[0..$effffff] of TPoint;
PPointArray = ^PointArray;
|
Также вместо p[i] можно использовать синтаксис (p + i)^, который приводит к тому же результату. Попробуем
таким образом посмотреть значение какого-нибудь элемента в инициализированном массиве:
procedure ShowPointByIndex(p: PPoint; Index: Integer);
begin
{$POINTERMATH ON}
ShowMessage('X: ' + (p+Index)^.X.ToString +
' Y: ' + (p+Index)^.Y.ToString);
{$POINTERMATH OFF}
end;
procedure TForm1.Button1Click(Sender: TObject);
var
pl: TPointList;
begin
FillList(@pl, Low(pl), High(pl));
// Смотрим 6-ой элемент (массив индексируется с нуля)
ShowPointByIndex(@pl, 5);
end;
|
Директива $POINTERMATH влияет только на типизированные указатели. Переменные типа Pointer не позволяют использовать
математические функции указателя, так как указатель типа фактически указывает на элемент void размером 0 байт.
Нетипизированные переменные или константы не затрагиваются, поскольку на самом деле они не являются указателями.
Такая вот арифметика!
|
При использовании материала - ссылка на сайт обязательна
|
|