Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Wert hinter Pointer erhalten (https://www.delphipraxis.net/82070-wert-hinter-pointer-erhalten.html)

Cöster 7. Dez 2006 16:46


Wert hinter Pointer erhalten
 
Hi!

Zunächst einmal: Hab es in der Hilfe und mit der Suchfunktion nicht finden können:

In einen TStack füge ich Integer per StackName.Push(@IntegerName) ein. Nun will ich den Integer wieder erhalten, der sich hinter dem Pointer verbirgt, der mir durch StackName.Pop geliefert wird. Wie funktioniert diese Umwandlung? Mit StackName.Pop^ geht's nicht.

DGL-luke 7. Dez 2006 17:10

Re: Wert hinter Pointer erhalten
 
:shock:

Du fügst einen Pointer auf einen Integer ein? Dann pass mal auf, dass dir der nicht wild wird...

ich würds so machen:

Delphi-Quellcode:
procedure PushInt(Val: Integer);
begin
  Stack.Push(Pointer(Val));
end;

function PopInt: Integer;
begin
  Result := Integer(Stack.Pop);
end;
(nur in Funktionen gekapselt, damit mans besser sieht)

Damit sagst du Delphi, es soll den Integer behandeln, als wärs ein Pointer. Du speicherst dann den Integer selber in die Liste und nicht nur die Adresse darauf.

EDIT: Vorausgesetzt, du alloziierst den Integer zuvor explizit, damit er beim Prozedurende nicht ungültig wird, kannst du ihn so dereferenzieren:

Delphi-Quellcode:
SomeInt := Integer(IntPtr^);
Wobei IntPtr (für "Pointer auf Integer") äquivalent zu Stack.Pop ist.

3_of_8 7. Dez 2006 17:16

Re: Wert hinter Pointer erhalten
 
Aua.

Delphi-Quellcode:
procedure PushInt(Val: Integer);
begin
  Stack.Push(Pointer(Val));
end;

function PopInt: Integer;
begin
  Result := Integer(Stack.Pop);
end;
Dann pusht er eine Variable auf den Stack und erhält die Adresse der Variable zurück.

Delphi-Quellcode:
procedure PushInt(Val: Integer);
begin
  Stack.Push(@Val);
end;

function PopInt: Integer;
begin
  Result:=PInteger(Stack.Pop)^;
end;
So schon eher.

EDIT: D'oh... Jetzt verstehe ich das... Klar, Lukes Code geht auch.

Cöster 7. Dez 2006 17:22

Re: Wert hinter Pointer erhalten
 
Zitat:

Zitat von 3_of_8
Delphi-Quellcode:
PInteger(Stack.Pop)^

Jap, so geht's. Danke

3_of_8 7. Dez 2006 17:27

Re: Wert hinter Pointer erhalten
 
Ich muss allerdings sagen, dass Lukes Lösung weniger Overkill hat. Da wird dem Stack der Integer nämlich als Pointer verkauft und reingespeichert.

Cöster 7. Dez 2006 17:36

Re: Wert hinter Pointer erhalten
 
Moment: Kann es sein, dass NUR DGL-Lukes Lösung funzt?

Dieser Code gibt erst 2 und dann 4 zurück:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
   Stack: TStack;
   Puffer: Integer;
begin
   Stack := TStack.Create;
   Puffer := 4;
   Stack.Push(Pointer(Puffer));
   Puffer := 2;
   Stack.Push(Pointer(Puffer));
   ShowMessage(IntToStr(Integer(Stack.Pop)));
   ShowMessage(IntToStr(Integer(Stack.Pop)));
   Stack.Free;
end;
Folgender hingegen 2mal hintereinander 2 :gruebel:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
   Stack: TStack;
   Puffer: Integer;
begin
   Stack := TStack.Create;
   Puffer := 4;
   Stack.Push(@Puffer);
   Puffer := 2;
   Stack.Push(@Puffer);
   ShowMessage(IntToStr(PInteger(Stack.Pop)^));
   ShowMessage(IntToStr(PInteger(Stack.Pop)^));
   Stack.Free;
end;
Warum???

DGL-luke 7. Dez 2006 17:39

Re: Wert hinter Pointer erhalten
 
Zusammenfassung, zur besseren verständlichkeit:

- Da ein Integer in die größe des Datentyps "Pointer" reinpasst (sprich identisch ist), kann man durch einen kleinen typecast (den 3_of_8 bedauerlicherunentschuldbarerweise als referenzierung verkannt hat) die Integers direkt in die Liste der Containerklasse speichern. Und auch so wieder rausholen. Das ist "common procedure" für die normalen Delphi-Listentypen.

Man kann aber auch:

- Einen Integer per New(SomeIntPtr) (typeof(SomeIntPtr) = PInteger) alloziieren und in den Stack nur die Adresse des Integers schreiben, die man dann natürlich beim Pushen ordentlich dereferenzieren muss.

EDIT: @Cöster: "Behaviour as usual".

Khabarakh 7. Dez 2006 17:40

Re: Wert hinter Pointer erhalten
 
@Cöster: Weil beide Zeiger auf "Puffer" zeigen und diese Variable nun einmal "2" enthält?
Zitat:

Zitat von DGL-luke
bedauerlicherunentschudbarerweise

:mrgreen:

3_of_8 7. Dez 2006 17:59

Re: Wert hinter Pointer erhalten
 
Ich hatte irgendwie in Erinnerung, dass Pointer(var) das gleiche wie @var macht... egal...

Dax 7. Dez 2006 18:28

Re: Wert hinter Pointer erhalten
 
3_of_8 --patch
Ich hatte irgendwie in Erinnerung, dass Addr(var) das gleiche wie @var macht... egal...

3_of_8 7. Dez 2006 18:40

Re: Wert hinter Pointer erhalten
 
Nein, ich habe es NICHT mit Addr() verwechselt. Ich dachte, dass der Typecast auf Pointer eine Referenzierung bewirkt. ;)

Hawkeye219 7. Dez 2006 18:59

Re: Wert hinter Pointer erhalten
 
Aber in Zukunft bitte nicht mehr die Adressen von lokalen Variablen in globalen Datenstrukturen ablegen, ok?

Gruß Hawkeye

Cöster 7. Dez 2006 19:20

Re: Wert hinter Pointer erhalten
 
Zitat:

Zitat von Hawkeye219
Aber in Zukunft bitte nicht mehr die Adressen von lokalen Variablen in globalen Datenstrukturen ablegen, ok?

Wie macht man das denn dann, wenn's jetzt keine Integer sind, die man in TStack, TList o. ä. ablegen will?

PS: Wo issn da jetzt eig. ne globale Datenstruktur?

Hawkeye219 7. Dez 2006 19:35

Re: Wert hinter Pointer erhalten
 
Zitat:

Zitat von Cöster
Wie macht man das denn dann, wenn's jetzt keine Integer sind, die man in TStack, TList o. ä. ablegen will?

Das hast Lukas bereits angedeutet. Den Speicherplatz dynamisch anfordern, die Daten reinkopieren und dann den Zeiger auf den Speicherblock im Stack oder in der Liste ablegen.

Zitat:

Wo issn da jetzt eig. ne globale Datenstruktur?
In Manuels Code ist der Stack außerhalb der Routinen PushInt und PopInt deklariert. Der Prozedurparameter Val ist eine lokale Variable, deren Wert nach der Rückkehr aus der Prozedur undefiniert ist. In deinem Beispiel (Beitrag #6) finden alle Aktionen (Erzeugen des Stacks, Push und Pop) innerhalb einer Routine statt. Das kann gutgehen - in der Praxis würde das aber wahrscheinlich niemand so machen.

Gruß Hawkeye

TStringlist 7. Dez 2006 19:38

Re: Wert hinter Pointer erhalten
 
edit: unwichtig.

3_of_8 7. Dez 2006 19:39

Re: Wert hinter Pointer erhalten
 
Ich habe auch nie gesagt, dass das sonderlich schön ist. TStack, TQueue, TList usw. sind nunmal für Klasseninstanzen gedacht. Wenn man primitive Datentypen da reinbasteln will, empfiehlt sich eine eigene Liste oder alternativ eine Wrapper-Klasse wie in Java.

Cöster 7. Dez 2006 19:55

Re: Wert hinter Pointer erhalten
 
Zitat:

Zitat von 3_of_8
Ich habe auch nie gesagt, dass das sonderlich schön ist. TStack, TQueue, TList usw. sind nunmal für Klasseninstanzen gedacht.

Ne, dafür sind TObjectStack, TObjectQueue und TObjectList gedacht.

Christian Seehase 7. Dez 2006 23:24

Re: Wert hinter Pointer erhalten
 
Moin Cöster,

ich hoffe nur, dass Dir klar geworden ist, dass das Ablegen der Adresse einer lokalen Variablen keine gute Idee ist, da diese nur innerhalb der lokalen Prozedur gültig ist.

Cöster 8. Dez 2006 13:36

Re: Wert hinter Pointer erhalten
 
Zitat:

Zitat von Christian Seehase
Moin Cöster,

ich hoffe nur, dass Dir klar geworden ist, dass das Ablegen der Adresse einer lokalen Variablen keine gute Idee ist, da diese nur innerhalb der lokalen Prozedur gültig ist.

Jap. Integer-Typen (bei kleineren wie Byte oder Word doch auch, oder?) kann man direkt in Pointer umwandeln (per Type Casting), ansonsten mit New erst Speicher reservieren, auf dem dann ein Wert abgelegt wird und dessen Adresse in der Liste, dem Stack oder was auch immer ablegen. Richtig?

Danke nochmal an alle :dp:


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:32 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