Присваивание значений указателю




Для инициализации указателей существует несколько возможностей.

  • процедура new отводит блок памяти в области динамических переменных и сохраняет адрес этой области в указателе;
  • специальная операция @ ориентирует переменную-указатель на область памяти, содержащую уже существующую переменную. Эту операцию можно применять для ориентации на статическую и динамическую переменную.
    Например,

type A=array[0..99] of char;
var X: array [0..49] of integer;
pA:^ A; {указатель на массив символов}

Объявлены переменные разных типов: массив из 50 целых чисел и указатель на массив символов. Чтобы указатель pA указывал на массив X, надо присвоить ему адрес X

pA:= @ X;

  • Существует единственная константа ссылочного типа nil, которая обозначает «пустой» адрес. Ее можно присваивать любому указателю.
  • Переменной-указателю можно присвоить значение другого указателя того же типа. Используя указательный тип pointer как промежуточный, можно присвоить значение одного указателя другому при несовпадении типов.

Операции с указателями

Для указателей определены только операции присваивания и проверки на равенство и неравенство. В Паскале запрещаются любые арифметические операции с указателями, их ввод-вывод и сравнение на больше-меньше.

Еще раз повторим правила присваивания указателей:

  • любому указателю можно присвоить стандартную константу nil, которая означает, что указатель не ссылается на какую-либо конкретную ячейку памяти;
  • указатели стандартного типа pointer совместимы с указателями любого типа;
  • указателю на конкретный тип данных можно присвоить только значение указателя того же или стандартного типа данных.

Указатели можно сравнивать на равенство и неравенство, например:

If p1=p2 then …..
If p1<>p2 then …..

В Паскале определены стандартные функции для работы с указателями:

  • addr(x) – тип результата pointer, возвращает адрес x (аналогично операции @), где x – имя переменной или подпрограммы;
  • seg(x) – тип результата word, возвращает адрес сегмента для x;
  • ofs(x) – тип результата word, возвращает смещение для x;
  • ptr(seg, ofs) – тип результата pointer, по заданному сегменту и смещению формирует адрес типа pointer.

Присваивание значений динамическим переменным

После того, как динамическая переменная объявлена, ей можно присваивать значения, изменять их, использовать в выражениях и т.д. Для этого используют следующее обращение: переменная_указатель^. Такое обращение называется операция разадресации (разыменования). Таким образом происходит обращение к значению, на которое указывает указатель, т.е. к данным. Если же за переменной_указателем значок ^ не стоит, то имеется в виду адрес, по которому расположены данные.

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

Например:

R^:= sqr(R^) + I^ -17;
q^:= 2; inc(q^); writeln(q^)

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

Адрес --->R:= sqr(R^) + I^ -17 <---вещественное выражение.
Вещественная переменная --->R^:= sqr(R) <---аргумент – адрес.

Рассмотрим пример работы с указателями:

 

Динамические структуры

Линейные списки (однонаправленные цепочки).

Списком называется структура данных, каждый элемент которой посредством указателя связывается со следующим элементом.

Каждый элемент связанного списка, во-первых, хранит какую-либо информацию, во-вторых, указывает на следующий за ним элемент. Так как элемент списка хранит разнотипные части (хранимая информация и указатель), то его естественно представить записью, в которой в одном поле располагается объект, а в другом – указатель на следующую запись такого же типа. Такая запись называется звеном, а структура из таких записей называется списком или цепочкой.

Лишь на самый первый элемент списка (голову) имеется отдельный указатель. Последний элемент списка никуда не указывает.

 

Описание списка

Пример описания списка

Type ukazat= ^ S;
S= record
Inf: integer;
Next: ukazat;
End;

В Паскале существует основное правило: перед использованием какого-либо объекта он должен быть описан. Исключение сделано лишь для указателей, которые могут ссылаться на еще не объявленный тип.

Формирование списка

Чтобы список существовал, надо определить указатель на его начало.

Пример описания списка

Type ukazat= ^S;
S= record
Inf: integer;
Next: ukazat;
End;

 

Создадим первый элемент списка:

New (u); {выделяем место в памяти}
u^. Next:= nil; {указатель пуст}
u^. Inf:=3;

Продолжим формирование списка. Для этого нужно добавить элемент либо в конец списка, либо в голову.

А) Добавим элемент в голову списка. Для этого необходимо выполнить последовательность действий:

  • получить память для нового элемента;
  • поместить туда информацию;
  • присоединить элемент к голове списка.

New(x);
Readln(x^.Inf);
x^. Next:= u;
u:= x;

Б)Добавление элемента в конец списка. Для этого введем вспомогательную переменную, которая будет хранить адрес последнего элемента. Пусть это будет указатель с именем hv (хвост).

x:= hv;

 

New(x^. next); {выделяем память для следующего элемента}

 

x:= x^.next;
x^.next:= nil;
x^. inf:= 5;
hv:=x;

Просмотр списка

While u<> nil do
Begin
Writeln (u^.inf);
u:= u^.next;>
end;



Поделиться:




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

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


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