Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Паскаль (ст 33).doc
Скачиваний:
2
Добавлен:
13.11.2019
Размер:
821.76 Кб
Скачать

4. Доступ к переменной по указателю.

Доступ к переменной по указателю называется косвенным доступом к переменной.

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

Например, чтобы увеличить значение переменной, на которую указывает указатель Р, можно записать:

P^ := P^ + 2; {доступ к переменной по указателю Р}

Пример 3.

Type

T = ^ Integer; {объявление ссылочного типа}

Var

A : T; {указатель А ссылается на динамическую переменную целого типа}

Y : Integer; {переменная целого типа}

B : ^ Real; {указатель В ссылается на динамическую переменную вещественного типа }

Begin

Y:=5;

New(A);

A^:=5;

New(B);

B^:=6.78;

End.

В примере 3 переменная Y – это статическая переменная целого типа, которая явным образом объявлена в разделе Var, имеет собственное уникальное имя, память под эту переменную выделяется при запуске программы и освобождается по окончании выполнения программы. Запись Y:=5; означает, что в переменную Y записывается значение «5».

Указатель А ссылается на динамическую переменную целого типа. При этом в переменной-указателе А содержится адрес переменной целого типа. Чтобы создать эту переменную в динамической памяти используется процедура New(A), которая выделяет память под целочисленную переменную, а в А помещает адрес этой переменной в динамической памяти. Таким образом, значение «5» в примере записывается в память по адресу, который содержится в переменной А. Аналогично, переменная В является указателем на вещественную переменную. С помощью процедуры New(B) выделяется память под вещественную переменную, а в указатель В записывается адрес этой переменной в динамической памяти. Запись B^:=6.78; означает, что значение «6.78» записывается в динамическую память по адресу, хранящемуся в переменной В.

Таким образом, в отличие от переменной Y, динамические переменные, на которые ссылаются указатели А и В не имеют собственного имени, не описываются в явном виде в разделе Var (описываются только указатели на эти переменные), память под них выделяется в любом месте программы с помощью процедуры New и может быть возвращена в кучу также в любом месте программы с помощью процедуры Dispose (см. ниже), как только отпадет необходимость в этих переменных.

5. Управление динамической памятью (процедуры New и Dispose).

Для выделения динамической памяти под динамическую переменную используется процедура New. После ее выполнения в куче выделяется память, равная размеру динамических переменных и указатели приобретают значения адресов динамических переменных. Например, после выполнения оператора New(A) (см. пример 3) в куче будет выделено 2 байта (под переменную типа Integer), а указатель А приобретет значение адреса выделенных в куче двух байтов. За одно обращение к куче процедурой New можно зарезервировать до 65521 байта динамической памяти.

Динамическую память можно не только занимать в куче, но и возвращать ее обратно. Для этого используется процедура Dispose. Например, операторы Dispose(A) и Dispose(B) вернут в кучу столько байт, сколько было выделено динамическим переменным A^ и B^, которые связаны с указателями А и В (см. пример 3).

Следует отметить, что оператор Dispose(<указатель>) не изменяет значение <указателя>, а лишь возвращает в кучу память, ранее связанную с этим указателем. Однако повторное применение процедуры к «свободному» (не связанному с определенным адресом динамической памяти) указателю приведет к возникновению ошибки периода выполнения. Чтобы пометить свободный указатель, программист может использовать зарезервированное слово Nil.

Nil означает специальный указатель, который «никуда не указывает». Можно представить такую ситуацию: в адресном пространстве оперативной памяти компьютера выделяется один адрес, по которому заведомо не может быть размещена ни одна переменная. На это место памяти и ссылается такой нулевой (пустой) указатель, который обозначается словом Nil. Указатель Nil считается константой, совместимой с любым ссылочным типом, поэтому его значение можно присваивать любому указателю. Обычно значение Nil присваивают указателю, когда указание надо отменить или в начале инициализации программы. Это позволяет проверять значение указателя, прежде чем присваивать ему какое-либо значение.

Примечание (!!!). Начальное значение указателя (при его объявлении в разделе описания переменных) может быть произвольным. Использование указателей, которым не присвоено значение процедурой New или каким-либо другим способом, никак не контролируется системой и может привести к непредсказуемым результатам.

К указателям можно применять операции отношения, в том числе и сравнение с Nil.

Пример.

Var

P : ^ Real; {объявление указателя на веществ. переменную}

Begin

P:=Nil; {присваивание Р значения «свободный указатель»}

If P = Nil {если Р – «свободный указатель»}

Then New(P); {то выделить из кучи память под веществ. переменную Р^}

Dispose(P); {вернуть в кучу память, выделенную под веществ. перем. Р^}

P:=Nil; {присваивание Р значения «свободный указатель»}

Задача

Сформировать случайным образом динамический массив целых чисел и вывести его на экран в обратном порядке (использовать указатели).

Program Primer_pointer;

Uses Crt;

Type

Massiv = Array[1..100] of Integer;

Pmas = ^ Massiv;

Var

i : Integer;

P:Pmas;

Begin

P:=Nil;

If P = Nil

Then New(P);

If P <> Nil

Then Begin

Randomize;

For i:=1 to 100

Do P^[i]:=Random(5)-11;

For i:=100 downto 1

Do Writeln(P^[i]);

Dispose(P);

P:=Nil;

End;

Readln;

End.

{тип – целочисл. массив из 100 элементов}

{тип - указатель на массив}

{параметр цикла}

{указатель на массив}

{присваивание Р зн-я «свободный указатель»}

{если Р – «свободный»}

{то выделить из кучи память под массив}

{если Р – не свободный}

{то формирование массива}

{с помощью генератора случайных чисел}

{вывод массива в обратном порядке}

{возврат памяти в кучу}

{«освобождение» указателя}