In C/C++ you always have
SizeOf(array[N] of T) = N * SizeOf(T);
In Pascal/Delphi you can use 'packed array' to be sure that the above assert is true, but does 'packed' specifier have any practical value for arrays in Delphi? I can't create an example of 'unpacked' array, the arrays seems always 'packed':
type
A = array[0..2] of Byte;
B = array[0..99] of A;
C = packed record
C1, C2, C3: Byte;
end;
D = array[0..99] of C;
procedure TForm10.Button1Click(Sender: TObject);
begin
Assert(SizeOf(A) = 3);
Assert(SizeOf(B) = 300);
Assert(SizeOf(D) = 300);
end;
(The C/C++ structures and Delphi records are different - they can be 'unpacked' so that the size of the structure is greater than the sum of fields' sizes due to the fields' alignment.)
It has no practical effect in Delphi. The only type it could reasonably affect is the type with the oddest alignment and size combination,
Extended
, which has a size of 10 and an alignment of 8. However, arrays ofExtended
are essentially packed already (though they still have an alignment of 8; if thepacked
directive worked like it did on records, they would have an alignment of 1).Why do I say arrays of
Extended
is the only type it could affect? There is no other Delphi type, built-in or that you can compose, which has a size that is not an integer multiple of its alignment (leaving aside older versions of Delphi, and some bugs). Alignment is the thing that makes records larger with padding; it causes fields to be spaced out so that every field starts at an offset which is an integer multiple of its type's alignment. In the analogous case with arrays, there is only one type involved, and if the size is already a multiple of the type's alignment, then there's no need for padding.Here's a program which shows how
Extended
affects size and alignment depending on whether it's wrapped in a record or not; you can addpacked
to the arrays, and see it makes no difference:More words about alignment and
packed
:packed
has another effect (on records) rather than just guaranteeing that there is no padding added: it also marks the record as having itself an alignment of 1. This has the negative effect of causing it to be frequently misaligned when it is used elsewhere. For purposes of language / OS interoperability, only in the case where the other language is not using OS alignment rules (normally meaning C alignment rules) should the packed directive be used. (Some Windows API headers have incorrect alignment for types defined within them, mind you, and have had to live with it ever since.) For purposes of compatibility with a file format, on the other hand, packed may be justified, but there are lots of other concerns there too, with respect to type choice (e.g. Integer was 2 bytes in 16-bit Delphi, but 4 bytes subsequently).Delphi tries to use C-compatible rules for alignment. In the past, it had some bugs here (particularly with records like TRec = record A, B: Extended end; versus TRec = record A: Extended; B: Extended end;), but these bugs should be fixed now
Delphi XE Help says this for dynamic arrays
Dynamic array memory layout (Win32 only):
Offset Contents
So, by that doc it is packed.