Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции Все Разделы.docx
Скачиваний:
17
Добавлен:
21.09.2019
Размер:
607.75 Кб
Скачать
    1. Многоуровневые записи

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

TStudent = Record

SelfStud: TStud;

Faculty: (FITR, MSF, ATF, MTF);

Military: Boolean;

End;

где поля Faculty и Military предназначены для хранения соответственно названия факультета, на котором обучается студент, и признака «служил в армии  / не служил». Пусть к тому же переменная Student имеет тип TStudent. Тогда в селекторах некоторых полей может появиться третья компонента, например,

Student.SelfStud.Fam:= ’Иванов’;

Student.SelfStud.Group:= ’107312’;

Student.Military:= True;

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

    1. Выравнивание и упакованные записи

Современные процессоры устроены таким образом, что они считывают данные отдельными порциями по 4 байта. Кроме того, эти порции всегда выравниваются по границе двойного слова. Это означает, что если данное «переходит» границу 4 байта, то процессору придется выдать две команды на считывание памяти: первая команда на считывание первой части данного, а вторая  на считывание второй части. Затем процессор соединит две части и отбросит ненужные биты.

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

TRec = Record

ValByte: Byte;

ValLongWord: LongWord;

End;

и переменная Rec этого типа. На первый взгляд применение функции sizeof к типу TRec (или к переменной Rec) даст размер 5 байт. Однако верным ответом будет 8 байт. Дело в том, что компилятор вставит между полями ValByte и ValLongWord три дополнительных байта, чтобы выровнять поле ValLongWord по 4-хбайтовой границе. Адреса записи Rec и ее первого поля ValByte будут совпадать, а адрес поля ValLongWord будет больше адреса ValByte на 4.

Если тип объявить следующим образом:

TRec = packed Record

ValByte: Byte;

ValLongWord: LongWord;

End;

то функция SizeOf(TRec) даст результат 5. Но в этом случае доступ к полю ValLongWord потребует больше времени, чем в предыдущем примере, поскольку граница 4 байт будет «пересекать» слот этого поля. Следовательно, на практике желательно пользоваться следующей рекомендацией: если используется ключевое слово packed, то сначала целесообразно объявить 4‑байтные поля, или поля, размер которых кратен 4, а потом уже все остальные.

Выравнивание данных помогает выполнять диспетчер распределения памяти Delphi. Он выравнивает не только 4‑байтные значения по границе 4 байт, но 8-байтные по границе 8 байт. Это имеет большое значение для вещественных переменных: операции с числами с плавающей точкой выполняются быстрее, если переменные выровнены по границе 8 байт.