Лекция 15. Динамические переменные — КиберПедия 

Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...

Лекция 15. Динамические переменные

2020-06-02 155
Лекция 15. Динамические переменные 0.00 из 5.00 0 оценок
Заказать работу

Оперативная память персонального компьютера имеет сегментную структуру. Сегмент -это участок памяти, имеющий максимальную длину 64К (65536 байт). При этом глобальные переменные и типизированные константы размещаются в сегменте данных. Такие переменные называются статическими, а память, выделяемая компилятором для их хранения называется статической памятью.

 

 

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

 

 

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

Как правило, в Турбо Паскале указатель связывается с некоторым типом данных. Такие указатели будем называть типизированными. Для объявления типизированного указателя используется значок ^, который помещается перед соответствующим типом,

То есть в программе объявляют не саму переменную нужного нам типа, а указатель на эту переменную, например:

var p: ^real;

здесь p – имя переменной-указателя; знак "^" показывает, что p является не обычной переменной, а указателем; real – тип той переменной, на которую указывает p. Переменная p представляет собой не что иное как адрес того места в памяти, где будет храниться сама динамическая переменная (в нашем случае число типа real).

 

В Турбо-Паскале можно объявлять указатель и не связывать его с конкретным типом данных:
Var
PP: Pointer;

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

В Турбо-Паскале можно передавать значения только между указателями, связанными с одним и тем же типом данных.

Var
P1,P2: ^Integer;
P3: ^Real;
PP:Pointer;
Begin
P1:= P2; {- верно}
P1:= P3; {- неверно}

но можно сделать так:
PP:= P3;
P1:= PP;
так как ограничение не распространяются на нетипизированные указатели. Но подобные операции часто путают программиста и чреваты смысловыми ошибками.

Динамическая память – это фактически единственная возможность обработки массивов данных большой размерности. Многие практические задачи трудно или невозможно решить без использования динамической памяти. Такая необходимость возникает, например, при разработке систем автоматизированного проектирования (САПР): размерность математических моделей, используемых в САПР, может значительно отличаться в разных проектах; статическое (т.е. на этапе разработки САПР) распределение памяти в этом случае, как правило, невозможно. Наконец, динамическая память широко используется для временного запоминания данных при работе с графическими и звуковыми средствами ПК.

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

Динамическую память обычно используют при:
1. обработке больших массивов данных;
2. разработке САПР;
3. временном запоминании данных при работе с графическими и звуковыми средствами
ЭВМ.

 

Для всех динамических переменных в памяти отводится пространство, называемое динамической областью, или кучей (хип). Перед тем как пользоваться динамической переменной, требуется выделить для неё место в куче. Это делается с помощью процедуры New, например:

New(p);

В результате такого действия в куче выделено место под переменную типа real, обратиться к ней можно, записав p^, например p^:=123.5.

Если потребуется изменить значение указателя, например, заставить его указывать на другую переменную, то старую переменную следует уничтожить, то есть объявить занимаемую старой переменной память свободной. Если этого не сделать, то при изменении указателя сама переменная станет мусором (место в памяти объявлено занятым, а получить к нему доступ уже невозможно).

Пример:

Var
I,J: ^Integer;
R: ^Real;
Begin
New(I); {под I выделяется область памяти,}
New(R)
End.

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

I^:= 2;
R^:= 2*Pi;
Допустима запись: R^:= Sqr (R^) + I^ - 17;
Но недопустима запись: R:= Sqr (R^) + I^ - 17; так как указателю R нельзя присвоить значение вещественного выражения.

Возврат динамической памяти обратно в кучу (то есть Уничтожение динамической переменной) осуществляется  Dispose: Dispose(p);

Dispose(R);
Dispose(I); - вернут в кучу, ранее забранные 8 байт.

 Dispose(Ptr) не изменяет значения указателя Ptr, а лишь возвращает в кучу память, связанную с этим указателем. Однако повторное применение процедуры к “свободному” указателю приведет к возникновению ошибки времени исполнения. Чтобы указать, что указатель свободен, нужно использовать зарезервированное слово Nil.

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

 

 

Рассмотрим еще пример. Пусть в программе описаны следующие указатели:

                          Var    D, P: ^Integer;

                                         K: ^Boolean;

Тогда допустимыми являются операторы присваивания

                          D:= P; K:= Nil;

поскольку соблюдается принцип соответствия типов. Оператор K:= D ошибочен, т.к. базовые типы у правой и левой части разные.

Если динамическая величина теряет свой указатель, то она становится "мусором". В программировании под этим словом понимают информацию, которая занимает память, но уже не нужна.

Пусть, в разделе операторов записано следующее:

NEW(D); NEW(P);

{Выделено место в динамической памяти под две целые переменные. Указатели получили соответствующие значения}

D^:= 3; P^:= 5;

{Динамическим переменным присвоены значения}

P:= D;

{Указатели P и D стали ссылаться на одну и ту же величину, равную 3}

WriteLn(P^, D^); {Дважды напечатается число 3}

Таким образом, динамическая величина, равная 5, потеряла свой указатель и стала недоступной. Однако место в памяти она занимает. Это и есть пример возникновения "мусора". На схеме показано, что произошло в результате выполнения оператора P:= D.

В Паскале имеется стандартная процедура, позволяющая освобождать память от данных, потребность в которых отпала. Ее формат:

                                    DISPOSE(<указатель>);

Например, если динамическая переменная P^ больше не нужна, то оператор

                                    DISPOSE(P)

удалит ее из памяти. После этого значение указателя P становится неопределенным. Особенно существенным становится эффект экономии памяти при удалении больших массивов.

 

 

Рассмотрим теперь операции, которые можно выполнять над указателями.

1. Присваивание. Указателю можно присваивать значение другого указателя такого же типа, а также значение nil, которое означает «ни на что не указывает». В указатель можно также положить адрес какой-либо переменной, например: p:=Addr(a); или p:=@a; хотя необходимость в этом возникает редко.

2. Сравнение. Два указателя можно сравнивать только на равенство (или неравенство). Можно сравнивать указатель с nil, с адресами переменных.

Const
P:^Real = Nil;
........
Begin
If P = Nil then
New (P);
........
Dispose(P);
P:= Nil;
End.

 

С динамическими переменными можно выполнять все действия, разрешённые для статических переменных, например:

if p^ >= q^ then p^:= q^;

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

var pa,pb: ^real;

Begin

new(pa); new(pb);

write('Введите a: '); readln(pa^);

write('Введите b: '); readln(pb^);

writeln('a+b=',pa^+pb^);

dispose(pa); dispose(pb);

readln;

end.

Program ex35_1;

Uses Crt;

Var

  px: ^char;

   i: byte;

Begin

  clrscr;

  new(px);

  for i:=0 to 255 do begin

   px^:=chr(i);

   write(i:3,'=',px^);

                      end;

  dispose(px);

  repeat until keypressed;

End.

 

Program ex35_2;

Uses Crt;

Type

  vect=array[1..10] of integer;

Var

  px: ^vect;

   i: byte;

Begin

        clrscr;

    new(px);

    for i:=1 to 10 do begin

       write('Введите ел-т массива N ',i,' ');

      Readln(px^[i]);

  end;

Writeln('Содержимое массива:');

for i:=1 to 10 do write(px^[i]:3);

dispose(px);

repeat until keypressed;

End.

Кроме описанных указателей существуют ещё так называемые нетипизированные указатели (тип pointer), которые могут служить указателями на переменные любых типов, однако необходимость в них возникает редко, поэтому рассматривать их подробно мы не будем.

 


Поделиться с друзьями:

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

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



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.045 с.