Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Статические и динамические переменные




 

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

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

Все объекты, описанные в разделе переменной, являются статическими. То есть их можно проконтролировать при статическом анализе текста программы, без ее выполнения (F9). Во время компиляции программы каждой статической переменной ставится в соответствие адрес ячейки памяти. Этот адрес в дальнейшем не меняется.

Далеко не каждую задачу можно решить, используя только статические переменные.

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

Опишем клиента так:

Type Person = record

                    ……..

                    ……..

          end{of record};

Эта запись – информация о клиенте, она может содержать любые необходимые сведения, например, фамилию, имя, отчество, возраст, марку автомобиля, характеристику неисправности, и т.д. и т. п.

Пусть заказчик предполагает длину очереди до const N = …; тогда описание самой очереди будет иметь вид:

Var L: array [1…N] of Person;

A: Person; {описание рабочей, или оперативной переменной}

I, J, K: byte; {или word, в зависимости от величены N индексы очереди}

C: integer; {или chart критерий выбора процедуры}

Программа должна обеспечивать выполнение опреций типа:

· Поставит в очередь,

· Обслужить, то есть изъять из очереди,

· Показать список очереди.

Обозначения: I – первый ожидающий обслуживания,

                   J – последнее свободное место в очереди.

Пишем программу:

Begin

I: =1; J:=1;{очередь пуста}

B: = False; {признак пустоты очереди}

Repeart

                              Write (‘операция: 1 – добавить,

2 –изъять,

3 – показать,

0 – конец работы’);

readln(c);

                      case c of

1: dobavit; {добавить}

2: izyat; {изъять}

3: perat; {печать}

0: exit; {выход}

end {of case}

until c = 0

end.

Теперь нужно написать три процедуры, что не составить трудности, и задача будет решена.

Итак, задача решена и довольно красиво, но остаются вопросы:

- что делать, если кто-то желает покинуть очередь изнутри, не дождавшись обслуживания,

- как поставить «своего» клиента внутрь очереди,

- что делать, если значение N наперед не известно?

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

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

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

Адреса ячеек памяти, где они будут созданы, непредсказуемы и поэтому анализу не подлежат.

Ссылочные типы (указатели)

 

Для работы с динамическими объектами используется ссылочный тип (или тип указатель). При этом в программе все действия над динамическими объектами описываются с помощью обыкновенных статических переменных. Но тип этих переменных – указатель (ссылочный тип). Это Pointer.

Тип Pointer – это фактически адрес хранения объекта.

Указатель может иметь значение адреса статической или динамической переменной. Особое значение указателя -<NIL>- - указатель, который указывает «в пустоту», в ничто.

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

В описании указателя P вводится тип T, на данные которого будет указатель P:

Type P=^T;

Множество значений типа P – неопределенное множество так называющихся идентифицирующихся величин (каждая из которых указывает на переменную типа T), в которое добавлено особое значение – Nil, которое ни на что не указывает.

Доступ к идентифицированным (динамическим) переменным осуществляется через указатели, значения которых соответствуют именам обычных переменных.

Указатели служат средством для формирования сложных и одновременно гибких структур данных.

Для объявления указателя используется значок ^, который помещается перед типом:

Var P1: ^Integer;

  P2: ^Integer;

Если, например, указатель (дадим ему имя Ptr) описан как

   Var Ptr : P;

и ему было присвоено некоторое значение, то Ptr^ будет обозначать динамическую переменную.

Содержательно любой ссылочный тип определяет множество значений, которые являются указателями на значения некоторого определенного типа. Для описания ссылочных типов используется символ «^» и индификатор типа, например:

Type P=^integer;

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

Имя в программе определение ссылочного типа, можно по общим правилам описать переменные этого типа. Ссылочные типы в описании переменных можно задавать как посредством идентификаторов, так и явно, например:

Пример. Type P= ^ integer;

Person = record

Word = 2 байта Name, SecondName, SurName: string [20],

   0…65000 Sex: (Male, Female);

                           Speciality: word; {индекс специальности}

                          End; {of record}

                    Omen: ^ Person;

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

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

Type P= ^ Base;

Даже если тип Base еще не был описан. Однако в таком случае тип Base должен быть описан далее в такой же части описания типов:

Type P= ^ Base;                     

     Base = record

              X, Y: real

               End; {of record}.

Реально значение ссылочных типов содержат адреса расположения в памяти конкретных значений базового типа. Для того, чтобы присвоить переменной ссылочного типа некоторое значение, можно воспользоваться операцией взятия указателя, которая строится из знака этой операции – символа @ (амперсант) и переменной любого типа.

Пример Var i: integer; {описание переменной}

                P1: ^ integer;

                 …………….

                P1: = @i; {указатель на целое}

В результате такого присваивания P1 получит в качества своего нового значения указатель на переменную i (или, попросту говоря, адрес переменной i), это можно наглядно представить в виде схемы:

P1: = I (P1 = адрес I)

J: = P1 (j= i)

        

P1

 
указатель


                                                  I

целое
                                                

 

 


Операция взятия указателя допустила до любых переменных, в том числе для элементов массивов, полей записи и т. д.

Пример Var A: array [1..10] of integer;

Для этого примера конструкция @ A[i] имеет смысл «указателя на i-ое целое в массиве A» и может участвовать в присваивании:

 P1:= @ A[i];

Ссылочные типы могут образовывать от любых типов, поэтому допустимо определение вида «указатель на указатель».

Пример type P= ^ integer;

                  P1 = ^ integer;

           Var F: ^ P;

                   I: integer;

Здесь переменная F в качестве своих возможных значений имеет множество указателей, ссылающихся на указатели, которые, в свою очередь, ссылаются на целые значения. Рассмотрим присваивание:

 P1: = @ A [i]; F: = P1?

 

         F

указатель
 

                                                          P1

указатель
                                                                                         i












Последнее изменение этой страницы: 2018-05-27; просмотров: 406.

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