Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.148.106.193] |
|
Сообщ.
#1
,
|
|
|
- Указатели - Pointers - В информатике существует целый ряд задач, в которых используются динамические структуры данных. Динамическими структурами данных считаются такие, размер которых заранее неизвестен и (или) изменяется в процессе выполнения программы. Связанные структуры являются динамическими к ним относятся: списки, стеки, очереди, графы, деревья. Динамическое размещение данных предусматривает использование динамической памяти, хотя в ней можно размещать величины любого типа. Динамическая память (куча) - это оперативная память компьютера, предоставляемая программе при её работе за вычетом сегмента данных, стека, памяти используемой системными и резидентными программами, и собственно телом самой исполняемой программы. Размер динамической памяти можно устанавливать из среды или из самой программы специальными директивами компилятора. Куча первоначально всегда свободна и заполняется от нижних адресов в области кучи. За стоянием кучи можно следить при помощи специально предопределённых в языке Pascal переменных типа указатель (Pointer): |
Сообщ.
#2
,
|
|
|
Для работы с указателями необходимо:
1. Описать указатель 2. Задать значение указателю 3. Операция разыменования 4. Освободить динамическую память 1) Описать указатель. При этом в статической области памяти будет выделено 4 байт и связано с его идентификатором. 2) Задать значение указателю Var K: Integer; P: Pointer; ..... P:= Addr(K); { Присвоить адрес переменной K } ..... Функция Addr(X) и операция @X, возвращают значение типа Pointer, являющееся началом области памяти, в которой размещается значение переменной Х. Переменная Х - может быть любого типа. Для выделения динамической памяти величинам при помощи типизированных указателей используется процедура New(TypePtr) Var Ptr :^integer; ....... New(Ptr); Для выделения динамической памяти величинам при помощи нетипизированных указателей используется процедура GetMem(TPtr,Size) Var Ptr:Pointer; .......... GetMem(Ptr,50); Для определения количества памяти необходимой для размещения величины какого - либо типа, в языке Pascal определена функция SizeOf(X). Var sameVar: byte; K:word; .......... K=SizeOf(sameVar); {k=1} .......... 3) Операция разыменования Суть её состоит в переходе от указателя к значению, на которое он указывает. Эта операци обозначается - идентификатор указателя^ . Результатом операции является значение величины, на которую указывает указатель, т.е. осуществляется доступ к той области памяти, с которой связан указатель. Разыменованному типизированному указателю можно присваивать значения того типа, которым он описан или присваивать его значения переменным того же типа. Аналогично и для нетипизированных указателей, но только надо следить, чтобы размер памяти указанной при создании нетипизированного указателя, совпадал с размером величины, которую мы заносим в память, или в которую мы считываем значение. Var I: ^Integer; R: ^Real; Begin New( I ); New( R ); I^:=200; R^:=3.1456; Writeln(I^); Writeln(R^); {На экран будут выведены значения 200 и 3.1456} End. 4) Освободить динамическую память По окончанию работы с величинами, размещёнными в динамической памяти, её надо освободить от них. Для типизированных указателей определена процедура Dispose(Идентификатор_указателя) Var Ptr :^integer; ............ new(ptr); ............ dispose(ptr); Для нетипизированных указателей определена процедура FreeMem(P, Size) Var ptr :Pointer; ............ GetMem(ptr,67); ............ FreeMem(ptr,67); , где P указатель типа Pointer, Size величина типа Word (количество освождаемой динамической памяти). Под действием данной процедуры освобождается участок памяти, начиная с адреса находящегося в указателе P, размером.Size. Значение указателя становится неопределённым. Данную процедуру нельзя применять к указателям значение, которых неопределено и следует внимательно следить за размером освобождаемой памяти. Применение этих процедур не изменяет значение переменной HeapPtr ,а освобождаемая динамическая память не учитывается как неиспользованная. На неё не будут указывать указатели при последующих вызовах процедур: New или GetMem. |
Сообщ.
#3
,
|
|
|
Вот вам и примеры
с типизированными указателями В этом примере приводятся способы использования типизированных указателей: 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^[i] 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. Скачать исходники: Прикреплённый файлpointer1.zip (1.22 Кбайт, скачиваний: 334) |