Einzelnen Beitrag anzeigen

SMO

Registriert seit: 20. Jul 2005
178 Beiträge
 
Delphi XE6 Professional
 
#6

AW: Array als Pointer übergeben

  Alt 28. Okt 2015, 13:31
Die 1 ist falsch.

Und zum Grundverständnis: es gibt Unterschiede zwischen statischen Arrays (TMyArray: Array [0..9] of Integer) und dynamischen Arrays (TIntArray: array of Integer). Die solltest du wenn möglich nicht hin und her casten, das kann zu Fehlern führen, wie in deinem Beispiel.

Kurz umrissen: statische Arrays sind ein zusammenhängender Speicherbereich. Die Länge ist nicht explizit vermerkt. Dynamische Arrays sind vergleichbar mit Strings und werden durch Compilermagic unterstützt (z.B. automatisches Freigeben von lokalen DynArray Variablen). Die DynArray Variablen sind implizite Pointer, die auf einen zusammenhängenden Speicherbereich zeigen (auf dem Heap). Direkt vor der Adresse, auf die gezeigt wird, stehen Metadaten, nämlich die Länge des Arrays sowie der RefCount.

Wenn du einen Cast wie "length(TIntArray(p))" machst, dann wird versucht, dieses Längenfeld zu lesen. Aber bei statischen Arrays existiert das gar nicht!


Um Arrays in Pointer umzuwandeln, benutze den Pointertyp, der zum Arrayelement passt. In deinem Beispiel also PInteger.

Delphi-Quellcode:
procedure TesteArray(p: PInteger; Count: Integer);
var
  i: Integer;
begin
  for i := 0 to Count - 1 do
  begin
    TuIrgendwasmit(p^);
    Inc(p); // Pointer auf das nächste Element bewegen
  end;
end;

// oder mit der Direktive POINTERMATH können typisierte Pointer
// direkt wie statische Arrays benutzt werden!

{$POINTERMATH ON}
procedure TesteArray(p: PInteger; Count: Integer);
var
  i: Integer;
begin
  for i := 0 to Count - 1 do
    TuIrgendwasmit(p[i]);
end;

// Aufruf:
var
  MyDynArray: array of Integer;
  MyStaArray: array [0..9] of Integer;

// geht, weil MyDynArray ein impliziter Pointer ist
TesteArray(PInteger(MyDynArray), Length(MyDynArray));

// geht NICHT, weil MyStaArray kein Pointer ist sondern ein 10*4 Bytes großer Speicherbereich
TesteArray(PInteger(MyStaArray), Length(MyStaArray));

// geht, weil sich an der Adresse von MyStaArray direkt der Speicherbereich mit den Elementen befindet
TesteArray(@MyStaArray, Length(MyStaArray));

// geht NICHT, weil sich an der Adresse von MyDynArray nur der implizite Pointer befindet!
TesteArray(@MyDynArray, Length(MyDynArray));


// geht IMMER, egal ob statisches oder dynamisches Array:
TesteArray(@MyStaArray[Low(MyStaArray)], Length(MyStaArray));
TesteArray(@MyDynArray[Low(MyDynArray)], Length(MyDynArray));

// bei dynamischen Arrays ist der niedrigste Index immer 0
// bei statischen Arrays kann man bei der Deklaration den niedrigsten Index auf beliebige Werte setzen,
// aber wenn man konsequent immer 0 benutzt, kann man natürlich schreiben:
TesteArray(@MyStaArray[0], Length(MyStaArray));
TesteArray(@MyDynArray[0], Length(MyDynArray));

Geändert von SMO (28. Okt 2015 um 14:15 Uhr)
  Mit Zitat antworten Zitat