Autor Beitrag
Distemix
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 13.11.08 19:51 
Hi,

Ich hab mich grade ein wenig mit Pointern in Delphi beschäftigt. Und ein kleines Program geschrieben, wo ich Speicher im Heap für eine Integer Variabel reserviere diese Speicherstelle in einem Pointer speicher. Ich habe der Integer Variabel noch den Wert 10 zugewiesen und mir den Wert 10 anzeigen lassen. So weit ging alles. Nun habe ich noch einen zweiten Pointer gemacht und wollte nicht den Wert sondern die Speicherstelle übergeben. Das hat nun dazu geführt, dass ich das Programm nicht mehr ausführen kann nicht mal wenn ich alle Zeilen auskommatier die dazu gekommen sind. Ich habe das ganze so versucht, wie ich auch in C++ mit Pointern gearbeitet habe.

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
program Project2;

uses
  SysUtils;
var
pointer1 : ^integer;
//pointer2 : ^integer;
begin
    new(pointer1);
    //new(pointer2);
    pointer1^ := 10;
  //  pointer2 :=   @pointer1;  Geht nicht?
    write(inttostr(pointer1^));
    //write(inttostr(pointer2^));
    readln;


end.


Thread-Start: Thread-ID: 3220. Prozess Project2.exe (2156)
Prozessstart: C:\Documents and Settings\jytf\My Documents\Borland Studio-Projekte\Project2.exe. Basisadresse: $00400000. Prozess Project2.exe (2156)
Modul laden: Project2.exe. Enthält Debug-Infos. Basisadresse: $00400000. Prozess Project2.exe (2156)
Modul laden: ntdll.dll. Ohne Debug-Infos. Basisadresse: $7C900000. Prozess Project2.exe (2156)
Modul laden: KERNEL32.dll. Ohne Debug-Infos. Basisadresse: $7C800000. Prozess Project2.exe (2156)
Modul laden: OLEAUT32.dll. Ohne Debug-Infos. Basisadresse: $77120000. Prozess Project2.exe (2156)
Modul laden: ADVAPI32.dll. Ohne Debug-Infos. Basisadresse: $77DD0000. Prozess Project2.exe (2156)
Modul laden: RPCRT4.dll. Ohne Debug-Infos. Basisadresse: $77E70000. Prozess Project2.exe (2156)
Modul laden: Secur32.dll. Ohne Debug-Infos. Basisadresse: $77FE0000. Prozess Project2.exe (2156)
Modul laden: GDI32.dll. Ohne Debug-Infos. Basisadresse: $77F10000. Prozess Project2.exe (2156)
Modul laden: USER32.dll. Ohne Debug-Infos. Basisadresse: $7E410000. Prozess Project2.exe (2156)
Modul laden: msvcrt.dll. Ohne Debug-Infos. Basisadresse: $77C10000. Prozess Project2.exe (2156)
Modul laden: ole32.dll. Ohne Debug-Infos. Basisadresse: $774E0000. Prozess Project2.exe (2156)
Modul laden: ShimEng.dll. Ohne Debug-Infos. Basisadresse: $5CB70000. Prozess Project2.exe (2156)
Modul laden: IMM32.dll. Ohne Debug-Infos. Basisadresse: $76390000. Prozess Project2.exe (2156)
Modul entladen: ShimEng.dll. Prozess Project2.exe (2156)
Modul laden: UxTheme.dll. Ohne Debug-Infos. Basisadresse: $5AD70000. Prozess Project2.exe (2156)
Quelltexthaltepunkt bei $00409159: C:\Documents and Settings\jytf\My Documents\Borland Studio-Projekte\Project2.dpr Zeile 9. Prozess Project2.exe (2156)
Erste Gelegenheit für Exception bei $7C812AEB. Exception-Klasse EInOutError mit Meldung 'E/A-Fehler 105'. Prozess Project2.exe (2156)

Das ist die Fehlerausgabe. Ich habe wohl nen ziemlichen Fehler gemacht glaub ich.. Würde mich über Hilfe freuen ;)
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 13.11.08 20:08 
Versuch es mal so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
    pointer1 : Pinteger;
    pointer2 : Pinteger;
begin
    new(pointer1);
    new(pointer2);
    pointer1^ := 10;
    pointer2 := @pointer1;
    writeln(inttostr(pointer1^));
    writeln(inttostr(integer(pointer2))); //so sollte es stimmen
    readln;
    Dispose(pointer1);
    Dispose(pointer2);
end.


[edit] Code korrigiert [/edit]


Zuletzt bearbeitet von DeddyH am Do 13.11.08 20:13, insgesamt 1-mal bearbeitet
Distemix Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 13.11.08 20:10 
Könntest du oder jemand anders vieleicht auch eine kleine erklärung geben, was bei mir der Fehler war und was bei deinem Beispiel jetzt besser ist damit ich auch was lerne?

Wäre nett ;)
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 13.11.08 20:16 
Wenn Du 2 mal einen Zeiger mit ^Typ deklarierst, sind das für Delphi 2 verschiedene Typen. Du kannst also entweder einen vordefinierten Typen verwenden wie ich oder Dir selbst einen definieren. Die Variablen müssen dann von diesem Typ sein, um als kompatibel erkannt zu werden.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
type PMyTyp = ^TMyTyp;

var var1: PMyTyp;
    var2: PMyTyp;
Distemix Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 13.11.08 20:27 
Okey Danke schon mal für die Antwort. Hätte da aber noch zwei fragen.

type MyType = ^TInteger; Ist das Richtig so? Muss ich also für TMyTyp den Datentyp angeben für den ich den Typen erstellen möchte?
writeln(inttostr(integer(pointer2))); //so sollte es stimmen Wieso muss ich da nochmal integer(pointer2) schreiben und kann nicht einfach pointer2^ in einen integer umwandeln?
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 13.11.08 20:31 
ausblenden Delphi-Quelltext
1:
2:
type PMyTyp = ^TMyTyp; //PMyTyp wird als Zeiger auf TMyTyp deklariert
     PInteger = ^integer; //ist bereits definiert, daher unnötige Typisierung


Was wolltest Du mit pointer2 denn ausgeben? Die Adresse von pointer1 oder die von pointer2 selbst? Hier mal mein Beispiel etwas erweitert, das sollte klarer sein:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type PInteger = ^Integer;

var
    pointer1 : PInteger;
    pointer2 : PInteger;
begin
    new(pointer1);
    new(pointer2);
    pointer1^ := 10;
    pointer2 := @pointer1;
    writeln('Inhalt von Pointer1: '+inttostr(pointer1^));
    writeln('Adresse von Pointer1 mittels Cast: '+inttostr(Integer(pointer1)));
    writeln('Adresse von Pointer1 mittels Pointer2: '+inttostr(pointer2^));
    writeln('Adresse von Pointer2 mittels Cast: '+inttostr(Integer(pointer2)));
    readln;
    Dispose(pointer1);
    Dispose(pointer2);
end.
Distemix Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 13.11.08 20:41 
Ahh jetzt glaube ich verstehe ich auch, was der Quelltext hier bewirkt:

writeln(inttostr(integer(pointer2))); Ich glkaube hier wird jetzt die Speicher Addresse in einen Integer umgewandelt damit man sie mit der Funktion inttostr in einen String umwandeln kann richtig?


type PMyTyp = ^TMyTyp; //PMyTyp wird als Zeiger auf TMyTyp deklariert
Und hier ist es völlig egal was für Namen ich vergebe? Kann ich auch einfach Tblub = ^Pblub schreiben? Und ist es notwendig das P und T mitzuschreiben?
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 13.11.08 20:42 
Ich habe meinen vorherigen Beitrag nochmal editiert. Und es hat sich allgemein eingebürgert, Typen mit dem Präfix T (für Type) und Zeiger mit dem Präfix P (für Pointer) zu benennen, so sieht man gleich, worum es sich handelt.
Distemix Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 13.11.08 20:49 
Also bekommt man durch Integer(pointer1) einfach die Speicheraddresse in einen Integerwert umgewandelt?
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 13.11.08 20:50 
Richtig, ein Pointer ist ja im Grunde nichts anderes als ein Integerwert mit "Sonderstatus".
Distemix Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 13.11.08 22:43 
Okey mich würde jetzt noch interesieren, wie Zeiger in Delphi in der Praxis eingesetzt werden. Also in C++ habe ich Zeiger meistens dafür eingesetzt um beispielsweise Klassen an Funktionen zu übergeben, weil es nicht so viel Rechenaufwand ist nur die Addressen zu übergeben. Oder ich hab Zeiger bei Singleton klassen eingesetzt.

Ich bin mir jetzt noch überhaupt nicht sicher wann und wie man Zeiger bei Delphi einsetzten kann und würde mich freuen, wenn hierauf mal jemand eingehen könnte :)
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Do 13.11.08 22:52 
Naja, Zeiger in Delphi werden z.B. für verkettete Listen eingesetzt, oder zum dynamischen reservieren von Speicher ala
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var p1: pointer;
begin
getmem (p1, 1000);
byte(p1^):=$111;
p1 := p1 +1;
integer(p1^):=$262;
freemem(p1, 100);
end;


Da wird 1000 byte reserviert, es wird ins erste byte $111 als byte geschrieben und in bytes 2 bis 5 der Wert $262 als integer.
Man sieht auch of in API-Funktionen die Argumente
ausblenden Delphi-Quelltext
1:
2:
Buffer: pointer,
var length: integer

, Wobei buffer ein Pointer auf einen (vorher reservierten!) Speicherbereich sein muss und length die Länge.