<<
>>

Записи

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

Запись — это неоднородная структура данных, в которой отдельные элементы идентифицируются именами.

В языке Pascal тип записи с к полями может представляться в виде

Каждое поле внутри записи имеет собственное имя.

Пример. Запись для комплексного числа может быть представлена так:

Объявления полей одинакового типа могут быть объединены:

На языке Ada подобный тип записывается в виде:

Изменение порядка полей в записи не меняет смысла программы, так как доступ к полям выполняется по имени, а не по относительной позиции (как в массиве).

266

Глава 10.
Составные типы данных

Объявление типа запись считается просто шаблоном. Память под запись выделяется при применении шаблона для объявления переменной: var x, y, z : complex;

С переменными x, y, z связана память, размещение в этой памяти определяется типом complex.

Если выражение Е обозначает запись с полем f, то само поле обозначается E.f.

Выражение E.f имеет значение и место расположения.

В z.re := x.re + y.re сумма значений полей x.re и y.re помещается в место расположения z.re.

В языках Pascal, Ada разрешены присваивания записей целиком: x := y;

Данное присваивание устанавливает для x.re значение y.re, а для x.im — значение y.im.

Заметим, что в языках Pascal и Ada объекты-записи не могут быть анонимными, для них предварительно должен объявляться тип с именем.

В языке С типу запись соответствуют структуры: struct {

;

;

}; " "

Доступ к элементам структур обеспечивается с помощью:

? операции-точки .;

? операции-стрелки -> .

Пример. Опишем структуру с именем block и заполним ее поля значениями: одно поле с помощью операции-точки, а другое поле — с помощью операции- стрелки.

Операция-стрелка ориентирована на использование указателя. Чтобы указатель ptr_a содержал адрес переменной а типа «структура», указатель инициируют. Забегая вперед, отметим, что адрес заносится с помощью операции взятия адреса &a.

В языке С имена чувствительны к регистру. Для того чтобы избавиться от влияния регистра на смысл имени, можно воспользоваться объявлением синонимов: typedef struct block Block;

Теперь имена block и Block соответствуют одной и той же структуре и можно применить, например, следующее объявление:

Block b;

Записи

267

В языках C++ и C# записи также поддерживаются с помощью типа struct. В C# struct является типом, экземпляры которого размещаются в стеке, в отличие от объектов классов, которые размещаются в куче. Тип struct в C++ и C# обычно используется только для инкапсуляции данных, которую мы будем обсуждать в главе 15. Структуры также включены в ML и F#.

В языках Python и Ruby записи могут быть реализованы как хеши, которые сами по себе могут быть элементами массивов.

В языках Java и C# записи могут определяться как элементы данных в классах, с вложенными записями, которые рассматриваются как вложенные классы. Элементы данных в таких классах служат полями записи.

Язык Lua позволяет использовать в качестве записей ассоциативные массивы. Например, рассмотрим следующее объявление:

professor.name = "Ivanov" professor.salary = 5000

Эти операторы присваивания создают таблицу (запись) по имени professor с двумя инициализированными полями name и salary.

Атрибуты объекта данных типа запись видны из приведенных выше объявлений:

1) количество полей;

2) тип данных для каждого поля;

3) имя для обозначения каждого поля.

Выбор полей является одной из основных операций над записями, например a.x. Она соответствует выбору элементов из массива при помощи индексов, но с одним отличием: индекс здесь всегда является буквальным именем поля и никогда не может быть вычисляемым значением. Приведенный пример выбора первого поля записи, a.x, соответствует выбору первого элемента массива, М[1], но для записей не существует операции, аналогичной операции выбора из массива М[Х], где Х — вычисляемое значение.

Операции над записью как единым целым обычно немногочисленны. Чаще всего используется операция присваивания одной записи некоторой другой, имеющей такую же структуру, например: struct block с;

a = c;

где c — запись, имеющая те же атрибуты, что и a.

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

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

Ведь объявление записи позволяет узнать размер каждого поля и его позицию внутри области памяти еще во время компиляции. Таким образом, смещение каждого поля также можно определить во время компиляции. Формула вычисления адреса ¿-го поля записи R имеет вид:

268

Глава 10. Составные типы данных

где base — базовый адрес области памяти, содержащей запись R, а R.j — поле под номером j. Суммирование требуется из-за возможного различия размеров каждого поля. Но эту сумму всегда можно определить заранее, во время компиляции, и тем самым получить значение смещения S. для ¿-го поля, так что во время выполнения потребуется добавить только базовый адрес области памяти:

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

struct ПреподавательКафедры { char Кафедра;

int Идентификатор;

} Преподаватель;

область памяти, отводимая под поле Идентификатор, должна начинаться на границе слова, и поэтому три байта между полями Кафедра и Идентификатор никак не используются и не содержат полезной информации. Фактически хранимая в памяти запись соответствует другому объявлению:

struct ПреподавательКафедры { char Кафедра;

char НеиспользуемыйБлок[3]; int Идентификатор;

} Преподаватель;

Возможны два варианта реализации операции присваивания целой записи некоторой другой, обладающей такой же структурой:

? простое копирование содержимого области памяти, хранящей первую запись, в область памяти, предназначенную для второй записи;

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

<< | >>

Еще по теме Записи:

  1. 10.8.1. Техника записи импровизаций
  2. ЗАВЕДИТЕ ПРИВЫЧКУ К ЗАПИСИ
  3. Глава первая Познакомьтесь с Крайоном Начало записей...
  4. Репортаж в записи
  5. Дети о взрослых из записей Д.С.
  6. Полторы дыры из записей Д.С.
  7. Стирание записи изображения и звука
  8. Упражнение ЗАПИСИ ДЛЯ ИСПРАВЛЕНИЯ КОНТРАКТА ДУШИ
  9. Прослушивание магнитофонной записи своего голоса проявляет детскую боязнь оказаться недостаточно хорошим.
  10. Врата настежь - налог на удобство из записей доктора Кстонова
  11. Очищение Старых Лемурийских Записей На рассвете Новой Эры на Земле
  12. Рассказывает потомственный мастер-кузнец Иван Николаевич Мельников, доживший до 99 лет (по моей давней записи).
  13. § 3. Средства записи и средства связи