![]() |
Array als Pointer übergeben
Hi,
ich will mal was versuchen. Weniger, weil es Sinn macht, sondern nur zu meinem Verständnis. Versucht habe ich das schon, ab hinbekommen habe ich es nicht. Ich möchte gerne mal ein Array in eine Pointer wandeln und hinterher wieder zurück. In der ersten Unit:
Delphi-Quellcode:
und in Unit2:
uses Unit2;
interface Type TMyArray: Array [0..9] of Integer; . . Type TForm1 = class(TForm) . . private MyArray: TMyArray; . . end; implementation procedure TForm1.ErzeugeArray; begin for i:=0 to 9 do MyArray[i]:=i; TesteArray(@MyArray); end;
Delphi-Quellcode:
So, das wird so sicherlich nicht funktionieren. Aber wie wäre es richtig und warum. Ich hab mich nun durch so einige Beispiele und Tutorials durch gelesen, aber ich raff das einfach nicht.
Type
TIntArray: array of Intger; procedure TesteArray(p: Pointer); begin for i:=0 to length(TIntArray(p))-1 do TuIrgendwasmit(TIntArray(p)[i]); end; |
AW: Array als Pointer übergeben
Zitat:
Statt:
Delphi-Quellcode:
eine TMyArray: Array of Integer; verwenden und diese mit Setlength() auf 10 setzen.
TMyArray: Array [0..9] of Integer;
|
AW: Array als Pointer übergeben
Zitat:
|
AW: Array als Pointer übergeben
Meine erste Antwort war falsch. Habe diese geändert.
|
AW: Array als Pointer übergeben
Du mußt p in TestArray derefenzieren.
|
AW: Array als Pointer übergeben
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)); |
AW: Array als Pointer übergeben
Wie die anderen schon gesagt haben: Es ist ein Unterschied ob du ein statisches oder ein dynamisches Array hast:
Statische Arrays:
Delphi-Quellcode:
type
PIntArray = ^TIntArray ; TIntArray = Array[0..9] of Integer; procedure TForm1.FormCreate(Sender: TObject); var MyArray: TIntArray; i: Integer; begin for i:=0 to 9 do MyArray[i]:=i; TesteArray(@MyArray); end; procedure TForm1.TesteArray(P: Pointer); var arr: TIntArray; i: Integer; begin arr := PIntArray(P)^; // Oder TIntArray(P^) for i:=0 to 9 do Memo1.Lines.Add(IntToStr(arr[i])); end; Dynamische Arrays:
Delphi-Quellcode:
Du kannst diese beiden Array-Typen nicht so ohne weiteres mischen. Zumindest nicht auf "Pointer Ebene".
type
TIntArray = Array of Integer; procedure TForm1.FormCreate(Sender: TObject); var MyArray: TIntArray ; i: Integer; begin SetLength(MyArray, 10); for i:=0 to 9 do MyArray[i]:=i; TesteArray(Pointer(MyArray)); // Dyn. Arrays sind bereits Pointer end; procedure TForm1.TesteArray(P: Pointer); var arr: TIntArray; i: Integer; begin arr := TIntArray(P); for i:=0 to 9 do Memo1.Lines.Add(IntToStr(arr[i])); end; Wie über mir auch schon gezeigt wurde kannst du auch statt dem Array einen Pointer auf das erste Element des Arrays übergeben (bei beiden Array-Typen wäre das @Array[erster_index]). Dann kannst du in deiner Methode über einen PInteger auf die Werte des Arrays zugreifen. Allerdings musst du der Methode dann zusätzlich die Anzahl der Elemente übergeben:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var MyArray: TIntArray; i: Integer; begin SetLength(MyArray, 10); for i:=0 to 9 do MyArray[i]:=i; TesteArray(@MyArray[0], Length(MyArray)); // Geht bei statischen Arrays genauso end; procedure TForm1.TesteArray(P: PInteger; Anzahl: Integer); var i: Integer; begin for i:=0 to Anzahl-1 do begin Memo1.Lines.Add(IntToStr(P^)); inc(P); // Pointer auf das nächstes Element des Arrays setzen end; end; |
AW: Array als Pointer übergeben
Vielen Dank. Ihr habt mir sehr weitergeholfen. Und Dank der Erklärung dabei habe ich das auch verstanden. :-D
|
AW: Array als Pointer übergeben
Ein Pointer ist eine Speicheradresse, nicht mehr und nicht weniger!
Falls Du eine Definition hast wie
Delphi-Quellcode:
dann wird der Inhalt des Speichers auf den der Pointer zeigt als
type
ta = Array [23..24] of Byte; tpa = ^ta;
Delphi-Quellcode:
interpretiert.
Array [23..24] of Byte;
Zeigt der Pointer auf einen String
Delphi-Quellcode:
so wird der Speicherinhalt immer noch als
var
p : tpa s : string[255]; ... p:=@s;
Delphi-Quellcode:
interpretiert.
Array [23..24] of Byte;
somit ist "Array als Pointer übergeben" nicht möglich. Möglich wäre es die Adresse eines Arrays zu übergeben wobei Du bei Dynamischen Array zwischen dem Inhalt des Arrays
Delphi-Quellcode:
und der Array-Variablen
@Myarray[0]
Delphi-Quellcode:
unterscheiden mußt. Bei statischen Arrays ist @MyArray=@MyArray[0]
@MyArray
Gruß K-H |
AW: Array als Pointer übergeben
Zitat:
Ich dachte eigentlich immer im Pointer steht die Adresse? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:14 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 by Thomas Breitkreuz