Ein wenig Pseudo-Code:
Delphi-Quellcode:
{$ALIGN Alignment}
type
TFoo = record
b : Byte; // $00
//x1: array [0..6] of Byte; // $01 Align(Min(Alignment, SizeOf(a)))
a : Extended; // $08
//x2: array [0..1] of Byte; // $12 Align(Min(Alignment, SizeOf(i)))
i : Integer; // $14
//x3: array [ ] of Byte // $18 Align(Min(Alignment, SizeOf(MaxMember))
end; // ($18)
Noch ein Edit um Missverständnissen vorzubeugen
SizeOf(...) in den Kommentaren ist das 'Alignment, welches für das Strukturmitglied benötigt wird'. SizeOf() ist insofern 'inkorrekt', da das Alignment eines strukturierten Typs das Alignment des 'größten Mitglieds' ist.
Beispiel:
Arr: array [0..1] of Word;
Die benötigte Ausrichtung für Arr ist die Größe eines Elements -
nicht SizeOf(Arr)!
Delphi-Quellcode:
Bar: record
A: Word; // 'größte erforderliche Ausrichtung' in Bar
B: Byte;
//x: Byte;
end;
SizeOf(Bar) ist 4. Die Ausrichtung für Bar selbst ist 2 (Bar.A erfordert eine Ausrichtung der Struktur an 2 Bytes).
Lösungsansatz für o.g. Problem:
Delphi-Quellcode:
type
PXType = ^TXType;
TXType = (
xByte,
xWord,
xInteger,
xDouble,
xExtended
);
const
XTypeSize: array [TXType] of Cardinal = (
SizeOf(Byte), // xByte
SizeOf(Word), // xWord
SizeOf(Integer), // xInteger
SizeOf(Double), // xDouble
SizeOf(Extended) // xExtended
);
type
// Dummy type to automatically detect the default alignment
TAlignmentDetection = record
A: Byte;
B: Int64;
end;
function GetRecordAlignment(const ATypes: array of TXType; AAlignment: Cardinal
): Cardinal;
var
Index: Integer;
Align: Cardinal;
begin
if AAlignment < 1 then
AAlignment := SizeOf(TAlignmentDetection) - SizeOf(Int64);
Result := 0;
for Index := Low(ATypes) to High(ATypes) do
begin
Align := XTypeSize[ATypes[Index]];
if Align > AAlignment then
Align := AAlignment;
if Align > Result then
Result := Align;
end;
end;
function GetRecordSize(const ATypes: array of TXType; AAlignment: Cardinal
): Cardinal;
var
ResultAlign: Cardinal;
Index: Integer;
XSize: Cardinal;
Align: Cardinal;
Spare: Cardinal;
begin
if AAlignment < 1 then
AAlignment := SizeOf(TAlignmentDetection) - SizeOf(Int64);
Result := 0;
ResultAlign := 0;
for Index := Low(ATypes) to High(ATypes) do
begin
XSize := XTypeSize[ATypes[Index]];
if XSize > 1 then
begin
Align := XSize;
if Align > AAlignment then
Align := AAlignment;
if Align > ResultAlign then
ResultAlign := Align;
Spare := Align - (Result mod Align);
if Spare < Align then
Inc(Result, Spare);
end;
Inc(Result, XSize);
end;
if ResultAlign > 1 then
begin
Spare := ResultAlign - (Result mod ResultAlign);
if Spare < ResultAlign then
Inc(Result, Spare);
end;
end;