Nie ma praktycznego wpływu na Delphi. Jedynym typem, jaki może w rozsądny sposób wpłynąć, jest typ o najdziwniejszym połączeniu i rozmiarze, Extended
, który ma rozmiar 10 i wyrównanie równe 8. Jednak tablice o numerach Extended
są zasadniczo zapakowane (chociaż nadal mają wyrównanie 8). jeśli dyrektywa packed
działała tak, jak w przypadku rekordów, miałyby wyrównanie 1).
Dlaczego mówię, że tablice o numerze Extended
to jedyny typ, na jaki może wpływać? Nie ma innego typu Delphi, wbudowanego lub który można komponować, który ma rozmiar, który nie jest całkowitą wielokrotnością jego wyrównania (pozostawiając na boku starsze wersje Delphi i kilka błędów). Wyrównanie jest tym, co sprawia, że rekordy są większe dzięki dopełnieniu; powoduje, że pola są rozstawione tak, że każde pole zaczyna się od przesunięcia, które jest wielokrotnością całkowitą jego wyrównania. W analogicznym przypadku z tablicami występuje tylko jeden typ, a jeśli rozmiar jest już wielokrotnością wyrównania typu, nie ma potrzeby wypełniania.
Oto program, który pokazuje, w jaki sposób Extended
wpływa na rozmiar i wyrównanie w zależności od tego, czy jest zapakowany w rekord, czy nie; można dodać packed
do tablic i zobacz, że nie ma różnicy:
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.
Więcej słów o wyrównanie i packed
: packed
ma inny efekt (na zapisy), a nie tylko gwarantuje, że nie ma wyściółka dodania: to również oznacza rekord jako sam w sobie wyrównanie 1. Ma to negatywny wpływ na to, że często jest niewyrównany, gdy jest używany gdzie indziej. Do celów zapewnienia zgodności operacyjnej języka/OS, tylko w przypadku, gdy inny język nie stosuje reguł wyrównania OS (zwykle oznaczających reguły wyrównania C) w przypadku użycia dyrektywy pakowania. (Niektóre nagłówki Windows API mają niepoprawne wyrównanie dla typów zdefiniowanych w nich, pamiętajcie, i musieliście z tym żyć od tego czasu). Z drugiej strony, pakowanie może być uzasadnione, ale istnieją wiele innych problemów także w odniesieniu do wyboru typu (np. liczba całkowita to 2 bajty w 16-bitowym Delphi, ale 4 bajty później).
Delphi próbuje użyć reguł kompatybilnych z C do wyrównania. W przeszłości występowały tutaj pewne błędy (szczególnie w przypadku rekordów takich jak TRec = rekord A, B: Extended end, versus TRec = record A: Extended, B: Extended end;), ale te błędy powinny teraz zostać naprawione
Zgaduję, że bez modyfikatora 'upakowanego 'przyszłe wersje kompilatora delphi mogą korzystać z macierzy niezbyt kompaktowych. Osobiście używam 'packed 'wtedy i tylko wtedy, gdy zależy mi na dokładnym układzie pamięci. – CodesInChaos