Указатели. Описание указателей




Указатели - это особый тип данных. В переменных этого типа хранятся адреса других переменных содержащих полезную для программы информацию. На первый взгляд может показаться, что использование указателей приводит к лишним затратам памяти и к усложнению программы, а также существе усложняет и сам процесс программирования. В данной главе мы, приведем такие примеры использования указателей, из которых станет ясно, что все дополнительные затраты на их хранение и обработку окупаются в полной мере. Работа с указателями предусмотрена не только в Pascal, но и в некоторых других языках программирования. Например, в языке С указатели используются практически в любой программе.

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

Указатели и адреса

Известно, что адресом переменной является адрес первого байта ячейки памяти, которая под нее отводится. Для данных структурных типов (массивов и записей) их адресом считается адрес первого байта первого элемента.

В Turbo Pascal существует возможность прямого доступа к любому байту оперативной памяти по его адресу при помощи определенных в модуле system массивов Mem, MemW и MemL, которые позволяют записать информацию или прочитать ее непосредственно из ячеек памяти (один, два или четыре байта). Это очень опасные действия, поэтому они исключены в 32- разрядных системах программирования. Все же дадим краткие пояснения для тех, кто работает в среде Borland (Turbo) Pascal.

В качестве индекса в этих массивах используется адрес, записанный в виде, принятом в DOS: сегмент: Смещение относительно начала сегмента. Такой странный способ записи адреса связан с тем, что в операционной системе DOS вся память разбита на сегменты, размеры которых не превышают 64 Кбайт. Для получения абсолютного адреса из пары сегмент Смещение система прибавляет к сегменту справа шестнадцатеричный ноль (это четыре нуля в двоичной системе), а затем складывает его со смещением. Таким способом можно адресовать 1 Мбайт памяти.

Например, начальный адрес видеобуфера запишется в виде $B800:$000, а обратиться к самому первому его байту можно так: Mem[$В800:$0000], к первым двум байтам — MemW[$B800:$0000], к первым четырем байтам — MemL [$B800:$0000]. Абсолютный адрес, соответствующий данной паре, — $B8000.

Еще один пример для любознательных — оператор mem[0:$41C]:=mem[0:$41А]; можно применить для принудительной очистки буфера клавиатуры. Здесь адрес маркера конца буфера клавиатуры приравнивается к адресу его начала. Конечно, в данном случае лучше воспользоваться средствами модуля crt.

Имеется еще один способ обращения к оперативной памяти — использование служебного слова absolute при описании переменной. В этом случае переменная будет располагаться именно по тому адресу в оперативной памяти, который указан после absolute. Разумеется, использование служебного слова absolute — столь же опасный способ, как и обращение к памяти через предопределенные массивы.

Однако absolute может использоваться и более безопасным способом, позволяя совмещать в памяти две переменные с разными именами. В языке Pascal есть специальная операция получения указателя на переменную (или процедуру) — она обозначается как @. Имеется также эквивалентная ей функция addr.

Например, @x или addr(х) — адрес переменной х.

Имеется и обратная операция получения значения переменной по ее адресу, которая обозначается знаком ^. Например, р^ переменная с адресом р.

В повседневной практике средства работы с адресами используются довольно редко. Основное назначение указателей состоит в том, чтобы обеспечить механизм использования в программе динамических переменных. Этот механизм мы и будем обсуждать подробно в следующих разделах.

Описание указателей

В Pascal имеются два различных вида указателей: типизированные и нетипизированные. Типизированный указатель — это указатель на переменную определенного типа, например, целого, строкового или типа массива Нетипизарованный указатель — это адрес первого байта области памяти, в которой может размещаться любая информация вне зависимости от ее типа.

Описание двух видов указателей выполняется по-разному:

var p1: ^integer; {указатель на переменную целого типа}

p2: ^string; {указатель на стоку}

p3 pointer; {нетипизированный указатель}

Заметим что тип pointer совместим со всеми типами указателей. В дальнейшем изложении для удобства имена всех указателей будем начинать с буквы p (pointer).

Каждый указатель размещается в сегменте данных или в стеке (если он объявлен в подпрограмме) и занимает там 4 байта. Это дополнительные “накладные расходы’ памяти. Поэтому обычные переменные очень редко создают и уничтожают динамически, оставляя эту возможность для больших совокупностей данных.

Чем больше размер динамической переменной, тем меньше доля накладных расходов. Например, при хранении в динамической памяти массивов больших размеров лишние 4 байта, затраченные на указатель, несущественны.

Списки

Списки представляют собой способ организации структуры данных, при которой элементы некоторого типа образуют цепочку. Для связывания элементов в списке используют систему указателей. В минимальном случае, любой элемент линейного списка имеет один указатель, который указывает на следующий элемент в списке или является пустым указателем, что интерпретируется как конец списка. На рис. 1 приведено понятийное изображение линейного списка.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-08-04 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: