![]() |
Record Größe zur Laufzeit bestimmen
bisher habe ich folgenden code um die größe von Records (Alignment 1,2,4,8) zur Laufzeit zu bestimmen
der Code sollte selbsterklärend sein, aber ich bin zu dumm dafür :( oder einfach zu müde, also wenn sich jemand dran machen will dann gerne :)
Delphi-Quellcode:
der obice dode ist im mom schwachsinn hab den mittlerweile wieder geändert :/ vill bekommts jemand hin :)
function GetRecordSize(types: array of TxType; Alignment: Integer): Integer;
var i: integer; max: integer; begin max := 0; for i := low(types) to high(types) do case types[i] of xInteger: if max < 4 then max := 4; xByte: if max < 1 then max := 1; xDouble: if max < 8 then max := 8; xExtended: if max < 10 then max := 10; xWord: if max < 2 then max := 2; end; if max < Alignment then Alignment := max; result := 0; for i := low(types) to high (types) do case types[i] of xInteger: if result mod 4 = 0 then inc(result,4) else inc (result,4 + alignment-(result mod alignment+1)); xByte: if result mod 1 = 0 then inc(result,1) else inc (result,1 + alignment-(result mod alignment+1)); xDouble: if result mod 8 = 0 then inc(result,8) else inc (result,8 + alignment-(result mod alignment+1)); xExtended: if result mod 10 = 0 then inc(result,10) else inc (result,10 + alignment-(result mod alignment+1)); xWord: if result mod 2 = 0 then inc(result,2) else inc (result,2 + alignment-(result mod alignment+1)); end; if result mod alignment <> 0 then result := result + alignment-(result mod alignment); end; type b = record b: byte; a: extended; i: integer; end; procedure TForm1.FormCreate(Sender: TObject); begin form1.caption := inttostr(GetRecordSize([xByte, xExtended, xInteger],8))+' '+inttostr(SizeOf(b)) |
Re: Record Größe zur Laufzeit bestimmen
:gruebel:
sizeof ist dir wohl nicht gut genug? |
Re: Record Größe zur Laufzeit bestimmen
Ne weil ich die Records erst zur laufzeit "selbst" erzeuge. Den Aufbau des Records kenn ich zur Designzeit nicht.
|
Re: Record Größe zur Laufzeit bestimmen
Moin Brechi,
mal abgesehen, dass ich die Sache etwas anders angehen würde (
Delphi-Quellcode:
), frage ich mich, was SizeOf da eigentlich bei einem Alignment von 8 veranstaltet.
function csGetRecordSize(const ATypes: array of TxType;const AiAlignment: Integer): Integer;
var i : Integer; iIncrement : Integer; begin Result := 0; for i := Low(ATypes) to High(ATypes)-1 do begin iIncrement := 0; case ATypes[i] of xInteger : if AiAlignment > 4 then iIncrement := AiAlignment else iIncrement := 4; xByte : iIncrement := AiAlignment; xDouble : if AiAlignment > 8 then iIncrement := AiAlignment else iIncrement := 8; xExtended : begin case AiAlignment of 1,2 : iIncrement := 10; 4 : iIncrement := 12; 8 : iIncrement := 16; end; end; xWord : if AiAlignment > 2 then iIncrement := AiAlignment else iIncrement := 2; end; inc(Result,iIncrement); end; if High(ATypes) > -1 then begin case ATypes[High(ATypes)] of xInteger : Inc(Result,4); xByte : Inc(Result,1); xDouble : Inc(Result,8); xExtended : Inc(Result,10); xWord : Inc(Result,2); end; end; end; SizeOf errechnet 24, was ja, wie man leicht von Hand nachrechnen kann, falsch ist. (Byte erfordert 8, Extended 16 und Integer 4 Byte, macht zusammen 28 ) :gruebel: Bei 1, 2 und 4 ist alles richtig. Ausprobiert hat ich es mit D7 und D2006 |
Re: Record Größe zur Laufzeit bestimmen
extended ist 10 vill liegts daran :) danek erstmal werd morgen mal testen
|
Re: Record Größe zur Laufzeit bestimmen
Also der Code von dir funtkoineit so auch nicht. Als Beispiel hab ich:
Delphi-Quellcode:
genommen und bei dir kommt da 25 raus. Das kann aber deshalb nicht sein, weil das Ergebnis immer mod alignment = 0 sein muss. (in dem Fall 24)
type xt = record
a: extended; b: integer; c: byte; end; begin writeln(SizeOf(xt),' ',csGetRecordSize([xExtended, xInteger, xByte], 8)); Ich versuch das heute nochmal selbst aber vill hat ja jemand so einen Code schonmal geschrieben :) Jedenfalls danke erstmal Christian. Du erhöst z.B. in deinem COde immer umd as Alignment das ist aber falsch. Bei einem Alignment von 8 und einem Record von Byte Integer ist die richtige Lösung 8 da es so aufgebaut wird: b---iiii Eigentlich weiß ich genua wie alles Berechnet wird war bisher nur zu dumm das umzusetzen, ok war auch spät nachdem man shcon 8 h geproggt hatte. :) |
Re: Record Größe zur Laufzeit bestimmen
Ein wenig Pseudo-Code:
Delphi-Quellcode:
Noch ein Edit um Missverständnissen vorzubeugen :)
{$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) 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:
Delphi-Quellcode:
Die benötigte Ausrichtung für Arr ist die Größe eines Elements - nicht SizeOf(Arr)!
Arr: array [0..1] of Word;
Delphi-Quellcode:
SizeOf(Bar) ist 4. Die Ausrichtung für Bar selbst ist 2 (Bar.A erfordert eine Ausrichtung der Struktur an 2 Bytes).
Bar: record
A: Word; // 'größte erforderliche Ausrichtung' in Bar B: Byte; //x: Byte; end; 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; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:45 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz