Verstehen und Verwenden von Zeigern in Delphi
elenabs/Getty Images
Auch wenn Zeiger in nicht so wichtig sind Delphi wie sie in C oder sind C++ , sie sind so ein 'einfaches' Werkzeug, dass fast alles damit zu tun hat Programmierung muss auf irgendeine Weise mit Zeigern umgehen.
Aus diesem Grund lesen Sie vielleicht, dass ein String oder Objekt eigentlich nur ein Zeiger ist oder dass ein Ereignishandler wie OnClick eigentlich ein Zeiger auf eine Prozedur ist.
Zeiger auf Datentyp
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 alles, was von einer Anwendung verwendet wird, irgendwo im Arbeitsspeicher des Computers gespeichert wird. Da ein Zeiger die Adresse einer anderen Variablen enthält, soll er auf diese Variable zeigen.
Meistens verweisen Zeiger in Delphi auf einen bestimmten Typ:
|_+_|Das Syntax Um einen Zeigerdatentyp zu deklarieren, wird a verwendet Caretzeichen (^) . 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 Integer-Variablen iValue gespeicherten Werts zuweisen.
Das @ Operator gibt die Adresse einer Variablen zurück (oder einer Funktion oder Prozedur, wie weiter unten zu sehen sein wird). Äquivalent zum @-Operator ist Addr-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 viel wie möglich typisierte Zeiger zu verwenden. Der Datentyp Pointer ist ein generischer Zeigertyp; es stellt einen Zeiger auf beliebige Daten dar.
Beachten Sie, dass, wenn '^' nach einer Zeigervariablen erscheint, der Zeiger dereferenziert wird; das heißt, es gibt den Wert zurück, der an der vom Zeiger gehaltenen Speicheradresse gespeichert ist. In diesem Beispiel hat die Variable j denselben Wert wie iValue. Es mag so aussehen, als hätte dies keinen Zweck, wenn wir einfach iValue j zuweisen können, aber dieses Stück Code steckt hinter den meisten Aufrufen der Win-API.
NILing-Zeiger
Nicht zugewiesene Zeiger sind gefährlich. Da Zeiger es uns ermöglichen, direkt mit dem Speicher des Computers zu arbeiten, könnten wir einen Zugriffsverletzungsfehler erhalten, wenn wir (aus Versehen) versuchen, an eine geschützte Stelle im Speicher zu schreiben. Aus diesem Grund sollten wir einen Zeiger immer auf NIL initialisieren.
NIL ist eine spezielle Konstante, die jedem Zeiger zugewiesen werden kann. Wenn einem Zeiger nil zugewiesen wird, verweist der Zeiger auf nichts. Delphi präsentiert zum Beispiel ein leeres
Zeichenzeiger
Die grundlegenden Typen PAnsiChar und PWideChar repräsentieren Zeiger auf AnsiChar- und WideChar-Werte. Das generische PChar repräsentiert einen Zeiger auf eine Char-Variable.
Diese Zeichenzeiger werden verwendet, um nullterminierte Zeichen zu manipulieren Saiten. Stellen Sie sich ein PChar als einen Zeiger auf eine nullterminierte Zeichenfolge oder auf das Array vor, das eine solche darstellt.
Zeiger auf Datensätze
Wenn wir einen Datensatz oder einen anderen Datentyp definieren, ist es üblich, auch einen Zeiger auf diesen Typ zu definieren. Dadurch ist es einfach, Instanzen des Typs zu manipulieren, ohne große Speicherblöcke kopieren zu müssen.
Die Möglichkeit, Zeiger auf Datensätze (und Arrays) zu haben, macht es viel einfacher, komplizierte Datenstrukturen als verknüpfte Listen und Bäume einzurichten.
|_+_|
Die Idee hinter verknüpften Listen besteht darin, uns die Möglichkeit zu geben, die Adresse des nächsten verknüpften Elements in einer Liste in einem NextItem-Datensatzfeld zu speichern.
Zeiger auf Datensätze können beispielsweise auch beim Speichern von benutzerdefinierten Daten für jedes Element der Baumansicht verwendet werden.
Verfahrens- und Methodenzeiger
Ein weiteres wichtiges Zeigerkonzept in Delphi sind Prozedur- und Methodenzeiger.
Zeiger, die auf die Adresse einer Prozedur oder Funktion zeigen, werden als prozedurale Zeiger bezeichnet. Methodenzeiger ähneln Prozedurzeigern. Anstatt auf eigenständige Prozeduren zu zeigen, müssen sie jedoch auf Klassenmethoden zeigen.
Der Methodenzeiger ist ein Zeiger, der Informationen über den Namen und das aufgerufene Objekt enthält.
Zeiger und Windows-API
Die häufigste Verwendung für Zeiger in Delphi ist die Anbindung an C- und C++-Code, was den Zugriff auf die Windows-API beinhaltet.
Windows API-Funktionen verwenden eine Reihe von Datentypen, die dem Delphi-Programmierer möglicherweise nicht vertraut sind. Die meisten Parameter beim Aufrufen von API-Funktionen sind Zeiger auf einen Datentyp. Wie oben erwähnt, verwenden wir in Delphi nullterminierte Strings, wenn wir 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 durchgeführt wird. Die Windows-API-Funktion SHBrowseForFolder ist ein Beispiel.
Zeiger- und Speicherzuordnung
Die wirkliche Stärke von Zeigern ergibt sich aus der Fähigkeit, während der Ausführung des Programms Speicher zu reservieren.
Dieses Stück 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.
|_+_|