#delphi #record #pascal
Вопрос:
Мои данные выглядят так (один байт каждые два» -«):
---- -- ---- ----
|0840|0C|00AD|0840|
---- -- ---- ----
Если я использую этот код: НЕПРАВИЛЬНО
Type TAlarmasRATP = record
Funcion : word;
Instancia : byte;
Err_0 : word;
Err_1 : word;
end;
Функция = 4008, Экземпляр = 0C, Err_0 = 08AD, Err_1 = 0040
Если я использую этот код: ПРАВИЛЬНО
Type TAlarmasRATP = record
Funcion : word;
Instancia : byte;
Err_0 : array [0..1] of byte;
Err_1 : array [0..1] of byte;
end;
Функция = 4008, Экземпляр = 0C, Err_0 = AD00, Err_1 = 4008
Почему первый не работает?
Комментарии:
1. Попробуй с собой
packed record
.2. @Оливье большое спасибо, это решает проблему.
Ответ №1:
При использовании типа записи поля выравниваются в соответствии со спецификацией Внутренние форматы данных — Типы записей:
Тип | выравнивание в байтах (32-битная платформа) |
---|---|
порядковый | размер типа (т. е. 1 для Byte , 2 для Word , 4 для Cardinal или 8 для Int64 ) |
реальный | 2 для Real48 , 4 для Single , 8 для Double и Extended |
ShortString |
1 |
Array |
То же, что и тип элемента массива |
Record |
Наибольшее выравнивание полей в записи |
Set |
Размер типа (1, 2 или 4), в противном случае всегда 1 |
все остальные | Определяется {$A} директивой |
Это означает: в первом объявлении записи Err_0
поле будет выровнено по Word
границе и добавит один байт заполнения после Instancia
поля.
Во втором объявлении записи Err_0
поле будет выровнено по Byte
границе, поскольку оно представляет собой массив Byte
, и после поля не будет отступа Instancia
. Поскольку запись не упакована, в конце структуры будет вставлен байт заполнения, поэтому размеры записей в обоих случаях будут округлены до 8.
Если вы используете packed
ключевое слово, все поля в записи будут упакованы до границы байта, а размер записи будет точно соответствовать сумме размеров полей без заполнения в конце.
Для того, чтобы иметь размер записи 7, вы можете просто объявить:
type TAlarmasRATP = packed record
Funcion : Word;
Instancia : Byte;
Err_0 : Word;
Err_1 : Word;
end;
Однако, если вам нужен размер 8, вам следует вручную добавить байт заполнения в конце, определив просто другое поле, которое вы никогда не используете:
type TAlarmasRATP = packed record
Funcion : Word;
Instancia : Byte;
Err_0 : Word;
Err_1 : Word;
Padding : Byte; // Unused
end;