Логическое и машинное представление записей

Запись - конечное упорядоченное множество полей, характери-

зующихся различным типом данных. Записи являются чрезвычайно

удобным средством для представления программных моделей реальных

объектов предметной области, ибо, как правило, каждый такой объ-

ект обладает набором свойств, характеризуемых данными различных

типов.

Пример записи - совокупность сведений о некотором студенте.

Объект "студент" обладает свойствами:

"личный номер" - характеризуется целым положительным числом,

"фамилия-имя-отчество" - характеризуется строкой символов и т.д.

Пример: var

rec:record

num :byte; { личный номер студента }

name :string[20]; { Ф.И.О. }

fac, group:string[7]; { факультет, группа }

math,comp,lang :byte; {оценки по математике, выч.тех-}

end; {нике, ин. языку }

В памяти эта структура может быть представлена в одном из

двух видов :

а) в виде последовательности полей, занимающих непрерывную

область памяти (рис. 3.10). При такой организации достаточно

иметь один указатель на начало области и смещение относительно

начала. Это дает экономию памяти, но лишнюю трату времени на вы-

числение адресов полей записи.

@rec│+0 │+1 │+21 │+29 │+37 │+38 │+39 │

├───────┼───────────────┼──────┼──────┼─────┼─────┼─────┤

│ 24 │ Иванов В.И. │ АП │ 54 │ 4 │ 5 │ 5 │

└───────┴───────────────┴──────┴──────┴─────┴─────┴─────┘

Рис. 3.10. Представление в памяти переменной типа record

в виде последовательности полей

б) в виде связного списка с указателями на значения полей

записи. При такой организации имеет место быстрое обращение к

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

Структура хранения в памяти связного списка с указателями на эле-

менты приведена на рис. 3.11.

Дескриптор записи

┌───────┬────────────┬────┐

│ rec │ student │ 7 │

├───────┼────┬───────┼────┤ ─┐

│ byte │ 1 │ num │ ──┼────> │

├───────┼────┼───────┼────┤ │

│ string│ 21 │ name │ ──┼────> │

├───────┼────┼───────┼────┤ │

│ string│ 8 │ fac │ ──┼────> │

├───────┼────┼───────┼────┤ │ Указатели значений

│ string│ 8 │ group │ ──┼────> ├─ полей записи

├───────┼────┼───────┼────┤ │

│ byte │ 1 │ math │ ──┼────> │

├───────┼────┼───────┼────┤ │

│ byte │ 1 │ comp │ ──┼────> │

├───────┼────┼───────┼────┤ │

│ byte │ 1 │ lang │ ──┼────> │

└───────┴────┴───────┴────┘ ┘

Рис. 3.11. Представление в памяти переменной типа record

в виде связного списка.

Примечание: для экономии объема памяти, отводимой под за-

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

вместо указателей, тогда в дескрипторе должны быть записаны соот-

ветствующие признаки.

В соответствии с общим подходом языка C дескриптор записи (в

этом языке записи называются структурами) не сохраняется до вы-

полнения программы. Поля структуры просто располагаются в смежных

слотах памяти, обращения к отдельным полям заменяются на их адре-

са еще на этапе компиляции.

Полем записи может быть в свою очередь интегрированная

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

языках программирования (COBOL, PL/1) при описании вложенных за-

писей указывается уровень вложенности, в других (PASCAL, C) -

уровень вложенности определяется автоматически.

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

такая же. Это связано прежде всего с тем, что компилятор должен

выделить для размещения записи память. Предположим, описана за-

пись вида:

type rec = record

f1 : integer;

f2 : char[2];

f3 : rec; end;

Как компилятор будет выделять память для такой записи? Для

поля f1 будет выделено 2 байта, для поля f2 - 2 байта, а поле f3

- запись, которая в свою очередь состоит из f1 (2 байта), f2 (2

байта) и f3, которое... и т.д. Недаром компилятор C, встретив по-

добное описание, выдает сообщение о нехватке памяти.

Однако, полем записи вполне может быть указатель на другую

такую же запись: размер памяти, занимаемой указателем известен и

проблем с выделением памяти не возникает. Этот прием широко ис-

пользуется в программировании для установления связей между одно-

типными записями (см. главу 5).