Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Wie kann man Informationen eines Arrays ermitteln? (https://www.delphipraxis.net/211396-wie-kann-man-informationen-eines-arrays-ermitteln.html)

KodeZwerg 10. Sep 2022 09:28

Wie kann man Informationen eines Arrays ermitteln?
 
Wie kann man Informationen eines Arrays ermitteln?
Was ich gerne hätte wäre eine Möglichkeit unter (altem und neuem) Delphi und unter FreePascal, also mit primitiven Bordmitteln die in allen Pascal's vorhanden sein sollten, Dinge über ein Array zu erfahren.
Im Endeffekt interessiert mich nur die tatsächliche Größe des Array im Speicher, aber vielleicht gibt es ja auch noch Möglichkeiten die mir mehr Informationen darüber ausspucken, wie zum Beispiel wieviel Dimensionen es hat, wieviel Elemente pro Dimension vorhanden sind etc...

Hat da jemand Erfahrung mit und kann mir dabei bitte weiter helfen?

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
type
  ArrayOfArrayOfDouble = array of array of double;
var
  Input: ArrayOfArrayOfDouble;
  i: Integer;
  size: Integer;
begin
  Randomize;
  SetLength(Input, 4);
  SetLength(Input[0], 2);
  SetLength(Input[1], 4);
  SetLength(Input[2], 6);
  SetLength(Input[3], 8);
  for i := Low(Input[0]) to High(Input[0]) do
    Input[0][i] := (Random(999) + 333) / (Random(9) + 3);
  for i := Low(Input[1]) to High(Input[1]) do
    Input[1][i] := (Random(999) + 333) / (Random(9) + 3);
  for i := Low(Input[2]) to High(Input[2]) do
    Input[2][i] := (Random(999) + 333) / (Random(9) + 3);
  for i := Low(Input[3]) to High(Input[3]) do
    Input[3][i] := (Random(999) + 333) / (Random(9) + 3);
  // macht man das so?
  size := 0;
  size := size + ((Length(Input[0]) * SizeOf(Input) + SizeOf(double)));
  size := size + ((Length(Input[1]) * SizeOf(Input) + SizeOf(double)));
  size := size + ((Length(Input[2]) * SizeOf(Input) + SizeOf(double)));
  size := size + ((Length(Input[3]) * SizeOf(Input) + SizeOf(double)));
end;
Ein Length() gibt mir ja nur die Elemente der ersten Ebene wieder.
Ein SizeOf() gibt mir nur die Größe des Pointers der Variable wieder.

Andreas13 10. Sep 2022 10:19

AW: Wie kann man Informationen eines Arrays ermitteln?
 
Hallo KodeZwerg,
die jeweiligen Längen der einzelnen Dimensionen eines mehrdimensionalen Arrays (= Matrix) kann man so abfragen:
Delphi-Quellcode:
Zeilen := Length(Matrix);   {1. Dimension}
Spalten := Length(Matrix[0]); {2. Dimension}
...
Grüße, Andreas

Uwe Raabe 10. Sep 2022 10:52

AW: Wie kann man Informationen eines Arrays ermitteln?
 
Zitat:

Zitat von Andreas13 (Beitrag 1511534)
die jeweiligen Längen der einzelnen Dimensionen eines mehrdimensionalen Arrays (= Matrix) kann man so abfragen:
Delphi-Quellcode:
Zeilen := Length(Matrix);   {1. Dimension}
Spalten := Length(Matrix[0]); {2. Dimension}
...

Wobei der Wert für jedes Subarray unterschiedlich sein kann. Z.B. kann
Delphi-Quellcode:
Matrix[1]
eine andere Länge haben als
Delphi-Quellcode:
Matrix[0]
.

Folgendes gilt für Delphi:
Bei einem statischen Array kann man die Anzahl der Dimensionen und auch die Länge jeder Dimension über TypeInfo direkt ermittelt werden. Bei dynamischen Arrays muss das iterativ geschehen und da gibt es auch keine Längeninformation (ist halt dynamisch).

Delphi-Quellcode:
uses
  System.TypInfo;

type
  ArrayOfArrayOfDouble = array of array of double;
var
  cnt: Integer;
  I: Integer;
  Input: ArrayOfArrayOfDouble;
  size: Cardinal;
  ti: PTypeInfo;
  td: PTypeData;
begin
  ti := TypeInfo(ArrayOfArrayOfDouble);
  if ti.Kind = tkDynArray then begin
    td := ti.TypeData;
    if (td.elType <> nil) and (td.elType^.Kind = tkDynArray) then begin
      cnt := 0;
      for I := 0 to Length(Input) - 1 do
        Inc(cnt, Length(Input[I]));
      size := cnt * td.elType^.TypeData.elSize;
    end
    else begin
      size := Length(Input) * td.elSize;
    end;
  end;
end;

Andreas13 10. Sep 2022 12:25

AW: Wie kann man Informationen eines Arrays ermitteln?
 
Uwe’s Lösung ist exzellent :thumb:, kann aber auf den ersten Blick nur von Profis verstanden werden. :oops:
Bisher habe ich meine variablen Matrixdimsionen folgendermaßen gelöst:
Delphi-Quellcode:
n_Zeilen := Length(Matrix); {1. Dimension}
n_Spalten:= Length(Matrix[0]);      {2. Dimension}
n_3D    := Length(Matrix [0][0]);  {3. Dimension}
n_4D    := Length(Matrix [0][0][0]); {4. Dimension}

// Beispiel für 2 Dimensionen:
  For Zeile:= 0 To n_Zeilen - 1 Do
  Begin
    n_Spalten:= Length(Matrix[Zeile]); // Zeilenlängen könnten variieren
    For Spalte:= 0 To n_Spalten - 1 Do
    Begin
     ...  
    End;
Bisher hat es stets funktioniert. Nennen wir das die Amateur-Variante... :)
Grüße, Andreas

KodeZwerg 10. Sep 2022 12:55

AW: Wie kann man Informationen eines Arrays ermitteln?
 
@Uwe, exzellent! Vielen Dank!! Jetzt wirds kniffelig wie ich das ganze in FPC hinbekomme :)

@Andreas, mir ging es nicht um "Length", mir geht es um die Größe wenn man das ganze zum Beispiel auf Festplatte sichern möchte oder in einem Stream schreiben etc, da brauch ich die Größe in Byte, aber vielleicht habe ich etwas übersehen, vielen Dank!

Uwe Raabe 10. Sep 2022 14:10

AW: Wie kann man Informationen eines Arrays ermitteln?
 
Mein Code benötigt sowohl die Variable als auch den Typ. Eigentlich sollte damit schon gesamte Array-Struktur bekannt sein und der Zugriff auf TypeInfo wäre überflüssig.
Delphi-Quellcode:
type
  ArrayOfArrayOfDouble = array of array of double;
var
  cnt: Integer;
  I: Integer;
  Input: ArrayOfArrayOfDouble;
  size: Cardinal;
begin
  cnt := 0;
  for I := 0 to Length(Input) - 1 do
    Inc(cnt, Length(Input[I]));
  size := cnt * SizeOf(Double);
end;
Mit den Delphi Generics gäbe das schon mehr Sinn, aber dann wird's vermutlich nichts mit älteren Delphis und FPC. (Dann hätte ich meinen Code auch etwas anders formuliert)

himitsu 10. Sep 2022 15:22

AW: Wie kann man Informationen eines Arrays ermitteln?
 
Jupp, die einfachen/alten RTTI TypeInfo-Dinge sollte FPC vom Delphi 1:1 kopiert haben und somit ginge der Code überall.

Ansonsten einfach mal in der System.pas bissl was abgucken, wie z.B. _DynArrayCopy.



Nicht vergessen SizeOf(TDynArrayTypeInfo) dazuzurechnen, wenn Length(arr)<>0 bzw arr<>nil .
Vor dem ersten Element liegen noch Verwaltungsdaten im RAM.
Aber dann fehlt auch noch der Speicher dahinter, also der ungenutzte Teil durch's MemoryAlignment.

KodeZwerg 10. Sep 2022 15:54

AW: Wie kann man Informationen eines Arrays ermitteln?
 
@Uwe, ach mein Held lass Dich mal drücken :mrgreen: Vielen Dank!

@Himitsu, ich vermute Du meinst zum Ergebnis einmal SizeOf(Input) hinzu addieren. Padding sollte doch wegen "I * SizeOf(Type)" bereits drinnen sein, oder aber ich hab Dich da falsch verstanden. Vielen Dank!

peterbelow 10. Sep 2022 16:09

AW: Wie kann man Informationen eines Arrays ermitteln?
 
Zitat:

Zitat von KodeZwerg (Beitrag 1511541)
@Uwe, exzellent! Vielen Dank!! Jetzt wirds kniffelig wie ich das ganze in FPC hinbekomme :)

@Andreas, mir ging es nicht um "Length", mir geht es um die Größe wenn man das ganze zum Beispiel auf Festplatte sichern möchte oder in einem Stream schreiben etc, da brauch ich die Größe in Byte, aber vielleicht habe ich etwas übersehen, vielen Dank!

Einen dynamischen Array mit mehr als einer Dimension kann man nicht en bloc in ein File/Stream etc. speichern, da der Inhalt halt nicht in einem zusammenhängenden Memory-Block abgelegt ist! Beispiel:

Delphi-Quellcode:
type
  T3DArray = array of array of array of double;
var
  L3DArray: T3DArray;

SetLength(L3DArray, 3,3,3);
L3DArray enthält einen Pointer, der auf einen array von 3 pointern zeigt, von denen jeder auf einen weiteren array von 3 pointern zeigt. Erst diese zeigen dann jeweils auf einen array von 3 double-Werten.

himitsu 10. Sep 2022 16:18

AW: Wie kann man Informationen eines Arrays ermitteln?
 
bei statischen Arrays geht es.

Delphi-Quellcode:
T = array[x..y] of array[x..y] of array[x..y] of double;


SizeOf(T) ist "dort" Alles.




Nein, SizeOf(Input) ist die Größe der Variable, welche auf das Array zeigt.
Und das sind immer 4 Byte, bzw. 8 Byte bei 64 Bit, da es einem SizeOf(Pointer) entspricht.

"IN" dem Array liegen aber vor dem Pointer, also vor dem ersten ArrayFeld @Input[0], noch die Verwaltungsdaten, welche TypInfo, Length und mehr enthalten (nur bei Length=0 gibt es das nicht), da Dieses z.B. für Copy und am Ende auch das FreeMem der Variable benötigt werden.

* für Größe der Daten in den Arrays, ist das unwichtig
* aber für Gesamtspeicher im RAM belegt es natürlich auch etwas


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:15 Uhr.
Seite 1 von 2  1 2      

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