Это не имеет практического эффекта в Delphi. Единственный тип, на который он может разумно повлиять, - это тип с самым странным сочетанием выравнивания и размера, Extended
, который имеет размер 10 и выравнивание 8. Однако массивы Extended
по существу уже упакованы (хотя они все еще имеют выравнивание 8; если бы директива packed
работала так же, как и на записях, они имели бы выравнивание 1).
Почему я говорю, что массивы Extended
- единственный тип, на который это может повлиять? Нет другого типа Delphi, встроенного или который вы можете составить, который имеет размер, который не является целым кратным его выравниванию (оставляя в стороне более старые версии Delphi и некоторые ошибки). Выравнивание - это то, что делает записи больше с отступом; это заставляет поля быть разнесенными так, чтобы каждое поле начиналось со смещения, которое является целым числом, кратным выравниванию его типа. В аналогичном случае с массивами задействован только один тип, и если размер уже кратен выравниванию типа, тогда нет необходимости в заполнении.
Вот программа, которая показывает, как Extended
влияет на размер и выравнивание в зависимости от того, находится ли он в записи или нет; вы можете добавить packed
к массивам, и вы увидите, что это не имеет значения:
type
TWrap = record
X: Extended;
end; // field size=10, align=8, => actual size=16
TArr1 = array[1..3] of TWrap; // 3*16 => size=48, align=8
TArr2 = array[1..3] of Extended; // 3 * 10 => size=30, align=8
TRec1 = record
A: Byte;
B: TArr1;
end;
TRec2 = record
A: Byte;
B: TArr2;
end;
var
x: TRec1;
y: TRec2;
begin
Writeln('Size of TArr1: ', SizeOf(TArr1));
Writeln('Alignment of TArr1: ', Integer(@x.B) - Integer(@x.A));
Writeln('Size of TArr2: ', SizeOf(TArr2));
Writeln('Alignment of TArr2: ', Integer(@y.B) - Integer(@y.A));
end.
Больше слов о выравнивании и packed
: packed
имеет другой эффект (на записи), а не просто гарантирует, что не добавлено заполнение: он также помечает запись как имеющую выравнивание 1. Это отрицательно. эффект от того, что он часто смещается, когда он используется в другом месте. Для целей взаимодействия языка / ОС, только в случае, когда другой язык не использует правила выравнивания ОС (обычно означающие правила выравнивания C), следует использовать упакованную директиву. (Обратите внимание, что некоторые заголовки Windows API имеют некорректное выравнивание для типов, определенных внутри них, и с тех пор им приходилось жить с этим.) С другой стороны, в целях совместимости с форматом файла упаковка может быть оправдана, но есть там также много других проблем, связанных с выбором типа (например, Integer составлял 2 байта в 16-битном Delphi, но 4 байта впоследствии).
Delphi пытается использовать C-совместимые правила для выравнивания. В прошлом здесь были некоторые ошибки (особенно с такими записями, как TRec = запись A, B: расширенный конец; по сравнению с TRec = запись A: расширенный; B: расширенный конец;), но эти ошибки должны быть исправлены сейчас