AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Record Größe zur Laufzeit bestimmen

Ein Thema von brechi · begonnen am 18. Apr 2008 · letzter Beitrag vom 21. Apr 2008
Antwort Antwort
brechi

Registriert seit: 30. Jan 2004
823 Beiträge
 
#1

Record Größe zur Laufzeit bestimmen

  Alt 18. Apr 2008, 20:21
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:
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))
der obice dode ist im mom schwachsinn hab den mittlerweile wieder geändert :/ vill bekommts jemand hin
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: Record Größe zur Laufzeit bestimmen

  Alt 18. Apr 2008, 20:31

sizeof ist dir wohl nicht gut genug?
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
brechi

Registriert seit: 30. Jan 2004
823 Beiträge
 
#3

Re: Record Größe zur Laufzeit bestimmen

  Alt 19. Apr 2008, 13:01
Ne weil ich die Records erst zur laufzeit "selbst" erzeuge. Den Aufbau des Records kenn ich zur Designzeit nicht.
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.117 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: Record Größe zur Laufzeit bestimmen

  Alt 19. Apr 2008, 16:22
Moin Brechi,

mal abgesehen, dass ich die Sache etwas anders angehen würde (

Delphi-Quellcode:
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;
), frage ich mich, was SizeOf da eigentlich bei einem Alignment von 8 veranstaltet.
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 )
Bei 1, 2 und 4 ist alles richtig.
Ausprobiert hat ich es mit D7 und D2006
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
brechi

Registriert seit: 30. Jan 2004
823 Beiträge
 
#5

Re: Record Größe zur Laufzeit bestimmen

  Alt 19. Apr 2008, 17:54
extended ist 10 vill liegts daran danek erstmal werd morgen mal testen
  Mit Zitat antworten Zitat
brechi

Registriert seit: 30. Jan 2004
823 Beiträge
 
#6

Re: Record Größe zur Laufzeit bestimmen

  Alt 21. Apr 2008, 08:45
Also der Code von dir funtkoineit so auch nicht. Als Beispiel hab ich:
Delphi-Quellcode:
type xt = record
  a: extended;
  b: integer;
  c: byte;
end;

begin
  writeln(SizeOf(xt),' ',csGetRecordSize([xExtended, xInteger, xByte], 8));
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)
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.
  Mit Zitat antworten Zitat
Benutzerbild von nicodex
nicodex

Registriert seit: 2. Jan 2008
Ort: Darmstadt
286 Beiträge
 
Delphi 2007 Professional
 
#7

Re: Record Größe zur Laufzeit bestimmen

  Alt 21. Apr 2008, 09:46
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;
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz