Содержание

Указатели

Для работы с указателями необходимо:

  1. Описать указатель
  2. Задать значение указателю
  3. Операция разыменования
  4. Освободить динамическую память

Описать указатель

При этом в статической области памяти будет выделено 4 байт и связано с его идентификатором.

нетипизированный

Var
Ptr1 : Pointer;

типизированный

  Type
  Base = Record
    Number : Byte;
    Name : String[30];
    Phith,Bio,Math : Char;
  End;
 
  Lang = Record
    Engl,Ukr,Rus : Char;
  End;
 
  Mass = Array[1..36] Of Base;
  LstPtr = ^List;
 
  List = Record
    Number,Ifo :Integer;
  end;
 
Var
  BegPtr,EndPtr : LstPtr;
  Ptr1 : ^Base;
  Ptr2 : ^Mass;
  Ptr3 : LstPtr;
  Ptr4 : ^String;
  Ptr5 : ^Integer;
  Ptr6 : ^Real;

Задать значение указателю

Var
  K: Integer;
  P: Pointer;
.....
P:= Addr(K); { Присвоить адрес переменной K }
.....

Функция Addr(X) и операция @X, возвращают значение типа Pointer, являющееся началом области памяти, в которой размещается значение переменной Х. Переменная Х - может быть любого типа.

Для выделения динамической памяти величинам при помощи типизированных указателей используется процедура New(TypePtr)

Var
Ptr :^integer;
.......
New(Ptr);

, где TypePtr - типизированный указатель. Под действием данной процедуры переменной TypePtr присваивается значение предопределённой переменной HeapPtr, в динамической памяти выделяется место соответственно типу указателя и значение переменной HeapPtr изменяется на величину этого типа. В дальнейшем при помощи этого указателя в динамической памяти можно размещать величины тип, которых соответствует типу типизированного указателя и иметь к ним доступ.

Для выделения динамической памяти величинам при помощи нетипизированных указателей используется процедура GetMem(TPtr,Size)

Var
Ptr:Pointer;
..........
GetMem(Ptr,50);

, где TPtr - нетипизированный указатель типа Pointer, Size - величина типа Word, количество выделяемой динамической памяти. Под действием данной процедуры переменной TPtr присваивается значение предопределённой переменной HeapPtr, в динамической памяти выделяется участок размером Size байт, значение переменной HeapPtr изменяется на величину параметра Size. В дальнейшем при помощи этого указателя в выделенном учаске динамической памяти можно размещать любые величины размером Size байт и иметь к ним доступ.

Для определения количества памяти, необходимой для размещения величины какого - либо типа, в языке Pascal определена функция SizeOf(X).

Var sameVar: byte;
  K:word;
..........
K=SizeOf(sameVar); {k=1}
..........

, где X - идентификатор переменной, функции или типа. В качестве своего результата функция возвращает величину типа Word - количество памяти в байтах необходимое для размещения X.

Операция разыменования

Суть её состоит в переходе от указателя к значению, на которое он указывает. Эта операци обозначается - идентификатор указателя^ . Результатом операции является значение величины, на которую указывает указатель, т.е. осуществляется доступ к той области памяти, с которой связан указатель. Разыменованному типизированному указателю можно присваивать значения того типа, которым он описан или присваивать его значения переменным того же типа.
Аналогично и для нетипизированных указателей, но только надо следить, чтобы размер памяти указанной при создании нетипизированного указателя, совпадал с размером величины, которую мы заносим в память, или в которую мы считываем значение.

Var
I: ^Integer;
R: ^Real;
Begin
New( I );
New( R );
I^:=200;
R^:=3.1456;
Writeln(I^); Writeln(R^); {На экран будут выведены значения 200 и 3.1456}
End.

Освободить динамическую память

По окончанию работы с величинами, размещёнными в динамической памяти, её надо освободить от них.

Для типизированных указателей определена процедура Dispose(Идентификатор_указателя)

Var
Ptr :^integer;
............
new(ptr);
............
dispose(ptr);

После выполнения этой процедуры значение типизированнго указателя неопределено и теряется значение, на которое он указывал. Дальнейшее использование этого указателя возможно, только после присваивания ему значения другого указателя или повторного применения процедуры New. Процедуру Dispose можно применять только к типизированным указателям значение, которых определено.

Для нетипизированных указателей определена процедура FreeMem(P, Size)

Var
ptr :Pointer;
............
GetMem(ptr,67); ............
FreeMem(ptr,67);

, где P указатель типа Pointer, Size величина типа Word (количество освождаемой динамической памяти). Под действием данной процедуры освобождается участок памяти, начиная с адреса находящегося в указателе P, размером.Size. Значение указателя становится неопределённым. Данную процедуру нельзя применять к указателям значение, которых неопределено и следует внимательно следить за размером освобождаемой памяти. Применение этих процедур не изменяет значение переменной HeapPtr ,а освобождаемая динамическая память не учитывается как неиспользованная. На неё не будут указывать указатели при последующих вызовах процедур: New или GetMem.

Примеры

Вот вам и примеры ;)

с типизированными указателями

В этом примере приводятся способы использования типизированных указателей:

type
   TInfo = record
     Size,
     Len: integer;
     ss:  string[20];
   end;
   Arr = array[1..10] of word;
 
var
   PInteger: ^Integer; { указатель на тип Integer }
   PInfo:    ^TInfo;   { указатель на тип TInfo}
   PA:       ^Arr;     { указатель на тип Arr}
   P:        Pointer;
   Sz,i:     word;
 
begin
 
     writeln;
     New (PInteger); { выделение памяти под указатель на тип Integer }
      PInteger^ := 123; { значению по адресу PInteger зададим значение }
      writeln ('Value = ', PInteger^);
     Dispose (PInteger); { освобождение зарезервированной памяти }
 
 
     New (PA); { выделение памяти под указатель на тип Arr }
      for i := 1 to 10 do PA^[i] := i * 2 - 1; { значениям массива по адресу PA зададим значения }
      for i := 1 to 10 do write (PA^[i] : 4); { выведем элементы массива по адресу PA }
     Dispose (PA); { освобождение зарезервированной памяти }
 
     New (PInfo); { выделение памяти под указатель на тип TInfo}
      with PInfo^ do { заносим данные в запись по адресу PInfo }
      begin
          writeln;
          { вводим значения переменных в записи }
          write ('Size: '); readln (Size);
          write ('Length: '); readln (Len);
          write ('String: '); readln (ss);
 
          writeln (Size:6, Len:6, ss:20); { выводим их значения }
      end;
     Dispose (PInfo); { освобождение зарезервированной памяти после использования записи }
 
end.

с нетипизированными указателями

В этом примере считывается файл в буффер с применением нетипизированного указателя и выводит количество цифр в нём.

var
     Digits: word;
 
procedure AnalizeBlock (Buf: pointer; Sz: word);
type
     ByteArr = Array [1..MaxInt] of char;
     PByteArr = ^ByteArr;
 
var
     i: word;
     P: PByteArr;
 
begin
     P := PByteArr (Buf);
     for i := 0 to Sz - 1 do
     begin
          if P^// in ['0'..'9'] then
            inc (Digits);
     end;
end;
 
var
   Buffer: Pointer;
   F:      file;
   Size,
   Count:  word;
 
begin
     writeln;
 
     Assign (F, 'test.dat');
     {$I-}
     Reset (F, 1);
     {$I+}
     if IOresult <> 0 then
          Halt (-1);
 
     Digits := 0;
     Size   := 4096;
 
     GetMem (Buffer, Size);
     if Buffer <> Nil then
     begin
          while Not EOF (F) do
          begin
               BlockRead (F, Buffer^, Size, Count);
               AnalizeBlock (Buffer, Size);
          end;
          FreeMem (Buffer, Size);
     end;
 
     Close (F);
 
     writeln ('File contains ', Digits, ' digits.');
end.