Obwohl Zeiger in Delphi nicht so wichtig sind wie in C oder C ++, sind sie ein so "grundlegendes" Werkzeug, dass fast alles, was mit Programmierung zu tun hat, in irgendeiner Weise mit Zeigern zu tun hat.
Aus diesem Grund lesen Sie vielleicht, wie ein String oder ein Objekt wirklich nur ein Zeiger ist, oder dass ein Ereignishandler wie OnClick tatsächlich ein Zeiger auf eine Prozedur ist.
Einfach ausgedrückt ist ein Zeiger eine Variable, die die Adresse von irgendetwas im Speicher enthält.
Um diese Definition zu konkretisieren, denken Sie daran, dass sich alles, was von einer Anwendung verwendet wird, irgendwo im Arbeitsspeicher des Computers befindet. Da ein Zeiger die Adresse einer anderen Variablen enthält, soll er auf diese Variable zeigen.
In den meisten Fällen verweisen Zeiger in Delphi auf einen bestimmten Typ:
var
iValue, j: ganze Zahl; pIntValue: ^ integer;
StartiValue: = 2001; pIntValue: = @iValue;… j: = pIntValue ^;
Ende;
Die Syntax zum Deklarieren eines Zeigerdatentyps verwendet a Caret (^). Im obigen Code ist iValue eine Variable vom Typ Integer und pIntValue ein Zeiger vom Typ Integer. Da ein Zeiger nichts anderes als eine Adresse im Speicher ist, müssen wir ihm die Position (Adresse) des in der Variablen iValue Integer gespeicherten Werts zuweisen.
Das @ Operator Gibt die Adresse einer Variablen zurück (oder eine Funktion oder Prozedur, wie weiter unten zu sehen sein wird). Entspricht dem @ -Operator Adr-Funktion. Beachten Sie, dass der Wert von pIntValue nicht 2001 ist.
In diesem Beispielcode ist pIntValue ein typisierter ganzzahliger Zeiger. Ein guter Programmierstil besteht darin, so oft wie möglich getippte Zeiger zu verwenden. Der Zeigerdatentyp ist ein generischer Zeigertyp. Es repräsentiert einen Zeiger auf beliebige Daten.
Beachten Sie, dass beim Anzeigen von "^" nach einer Zeigervariable der Verweis auf den Zeiger aufgehoben wird. Das heißt, es wird der Wert zurückgegeben, der an der vom Zeiger gehaltenen Speicheradresse gespeichert ist. In diesem Beispiel hat die Variable j den gleichen Wert wie iValue. Es mag so aussehen, als hätte dies keinen Zweck, wenn wir einfach iValue zu j zuweisen können, aber dieser Code steckt hinter den meisten Aufrufen von Win API.
Nicht zugewiesene Zeiger sind gefährlich. Da Zeiger uns direkt mit dem Arbeitsspeicher des Computers arbeiten lassen und wir versuchen, (versehentlich) an einen geschützten Speicherort zu schreiben, kann ein Zugriffsverletzungsfehler auftreten. Aus diesem Grund sollten wir immer einen Zeiger auf NIL initialisieren.
NIL ist eine spezielle Konstante, die jedem Zeiger zugewiesen werden kann. Wenn nil einem Zeiger zugewiesen ist, verweist der Zeiger auf nichts. Delphi präsentiert beispielsweise ein leeres dynamisches Array oder einen langen String als Nullzeiger.
Die Grundtypen PAnsiChar und PWideChar repräsentieren Zeiger auf AnsiChar- und WideChar-Werte. Das generische PChar repräsentiert einen Zeiger auf eine Char-Variable.
Mit diesen Zeichenzeigern werden nullterminierte Zeichenfolgen bearbeitet. Stellen Sie sich ein PChar als Zeiger auf einen nullterminierten String oder auf das Array vor, das einen darstellt.
Wenn wir einen Datensatz oder einen anderen Datentyp definieren, ist es üblich, auch einen Zeiger auf diesen Typ zu definieren. Auf diese Weise können Instanzen des Typs einfach bearbeitet werden, ohne dass große Speicherblöcke kopiert werden müssen.
Die Möglichkeit, Zeiger auf Datensätze (und Arrays) zu haben, erleichtert das Einrichten komplizierter Datenstrukturen als verknüpfte Listen und Bäume.
Art
pNextItem = ^ TLinkedListItem
TLinkedListItem = AufzeichnungsName: String; iValue: Integer; NextItem: pNextItem;
Ende;
Die Idee hinter verknüpften Listen ist, uns die Möglichkeit zu geben, die Adresse zum nächsten verknüpften Element in einer Liste in einem NextItem-Datensatzfeld zu speichern.
Zeiger auf Datensätze können beispielsweise auch zum Speichern benutzerdefinierter Daten für jedes Element der Strukturansicht verwendet werden.
Ein weiteres wichtiges Zeigerkonzept in Delphi sind Prozedur- und Methodenzeiger.
Zeiger, die auf die Adresse einer Prozedur oder Funktion verweisen, werden als prozedurale Zeiger bezeichnet. Methodenzeiger sind Prozedurzeigern ähnlich. Anstatt jedoch auf eigenständige Prozeduren zu verweisen, müssen sie auf Klassenmethoden verweisen.
Der Methodenzeiger ist ein Zeiger, der Informationen über den Namen und das Objekt enthält, die aufgerufen werden.
Die häufigste Verwendung für Zeiger in Delphi ist die Anbindung an C- und C ++ - Code, einschließlich des Zugriffs auf die Windows-API.
Windows-API-Funktionen verwenden eine Reihe von Datentypen, die dem Delphi-Programmierer möglicherweise unbekannt sind. Die meisten Parameter beim Aufrufen von API-Funktionen sind Zeiger auf einen Datentyp. Wie oben erwähnt, verwenden wir in Delphi nullterminierte Zeichenfolgen, wenn Sie Windows-API-Funktionen aufrufen.
Wenn ein API-Aufruf einen Wert in einem Puffer oder Zeiger auf eine Datenstruktur zurückgibt, müssen diese Puffer und Datenstrukturen in vielen Fällen von der Anwendung zugewiesen werden, bevor der API-Aufruf erfolgt. Die SHBrowseForFolder-Windows-API-Funktion ist ein Beispiel.
Die eigentliche Stärke von Zeigern beruht auf der Möglichkeit, während der Ausführung des Programms Speicher freizugeben.
Dieser Code sollte ausreichen, um zu beweisen, dass die Arbeit mit Zeigern nicht so schwierig ist, wie es zunächst scheinen mag. Es wird verwendet, um den Text (Beschriftung) des Steuerelements mit dem bereitgestellten Handle zu ändern.
Verfahren GetTextFromHandle (hWND: THandle);
var pText: PChar; // ein Zeiger auf char (so)TextLen: integer;
Start
Länge des Textes ermittelnTextLen: = GetWindowTextLength (hWND);
Speicher zuweisen
GetMem (pText, TextLen); // nimmt einen Zeiger
Hole den Text des SteuerelementsGetWindowText (hWND, pText, TextLen + 1);
zeige den Text anShowMessage (String (pText))
Speicher freigebenFreeMem (pText);
Ende;