Ответ 1
Он не имеет практического эффекта в 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. Это имеет отрицательный эффект, вызвавший его частое смещение, когда он используется в другом месте. Для обеспечения совместимости языка/ОС только в том случае, если другой язык не использует правила выравнивания ОС (обычно это означает правила выравнивания по С), следует использовать упакованную директиву. (Некоторые заголовки API Windows имеют неправильное выравнивание для типов, определенных внутри них, помните о вас, и им приходилось жить с ним с тех пор.) С другой стороны, с точки зрения совместимости с форматом файлов, они могут быть оправданы, но существуют существует множество других проблем в отношении выбора типа (например, Integer был 2 байта в 16-битном Delphi, но 4 байта впоследствии).
Delphi пытается использовать C-совместимые правила для выравнивания. В прошлом у него были некоторые ошибки (особенно с такими записями, как TRec = запись A, B: Extended end, по сравнению с TRec = запись A: Extended; B: Extended end;), но теперь эти ошибки должны быть исправлены