Verstehen und Verwenden von Zeigern in Delphi

click fraud protection

Auch wenn Zeiger in nicht so wichtig sind Delphi wie sie in C oder sind C ++Sie sind so ein "grundlegendes" Werkzeug, dass fast alles damit zu tun hat Programmierung muss in irgendeiner Weise mit Zeigern umgehen.

Aus diesem Grund können Sie lesen, wie eine Zeichenfolge oder ein Objekt wirklich nur ein Zeiger ist oder dass ein Ereignishandler wie OnClick tatsächlich ein Zeiger auf eine Prozedur ist.

Zeiger auf Datentyp

Einfach ausgedrückt ist ein Zeiger eine Variable, die die Adresse von allem im Speicher enthält.

Um diese Definition zu konkretisieren, denken Sie daran, dass alles, was von einer Anwendung verwendet wird, irgendwo im Speicher des Computers gespeichert ist. Da ein Zeiger die Adresse einer anderen Variablen enthält, soll er auf diese Variable verweisen.

Meistens verweisen Zeiger in Delphi auf einen bestimmten Typ:

var
iValue, j: ganze Zahl; pIntValue: ^ integer;
Start
iValue: = 2001; pIntValue: = @iValue;... j: = pIntValue ^;
Ende
;

Das Syntax Um einen Zeigerdatentyp zu deklarieren, wird a verwendet

instagram viewer
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 iValue-Ganzzahlvariablen gespeicherten Werts zuweisen.

Das @ Operator Gibt die Adresse einer Variablen zurück (oder eine Funktion oder Prozedur, wie unten gezeigt wird). Entspricht dem @ -Operator Addr-Funktion. Beachten Sie, dass der Wert von pIntValue nicht 2001 ist.

In diesem Beispielcode ist pIntValue ein typisierter Ganzzahlzeiger. Ein guter Programmierstil besteht darin, so oft wie möglich typisierte Zeiger zu verwenden. Der Zeigerdatentyp ist ein generischer Zeigertyp. Es stellt einen Zeiger auf beliebige Daten dar.

Beachten Sie, dass wenn "^" nach einer Zeigervariable angezeigt wird, der Zeiger nicht mehr referenziert 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 j einfach iValue zuweisen können, aber dieser 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 Arbeitsspeicher des Computers zu arbeiten, kann es zu einem Fehler bei der Zugriffsverletzung kommen, wenn wir (versehentlich) versuchen, an einen geschützten Speicherort im Speicher zu schreiben. Aus diesem Grund sollten wir immer einen Zeiger auf NIL initialisieren.

NIL ist eine spezielle Konstante, die jedem Zeiger zugewiesen werden kann. Wenn einem Zeiger Null zugewiesen ist, verweist der Zeiger auf nichts. Delphi präsentiert zum Beispiel eine leere dynamisches Array oder eine lange Zeichenfolge als Nullzeiger.

Zeichenzeiger

Die Grundtypen 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 zu bearbeiten Saiten. Stellen Sie sich ein PChar als Zeiger auf eine nullterminierte Zeichenfolge oder auf das Array vor, das eine darstellt.

Zeiger auf Aufzeichnungen

Wenn wir einen Datensatz oder einen anderen Datentyp definieren, ist es üblich, auch einen Zeiger auf diesen Typ zu definieren. Dies macht es einfach, Instanzen dieses Typs zu manipulieren, ohne große Speicherblöcke zu kopieren.

Die Möglichkeit, Zeiger auf Datensätze (und Arrays) zu haben, erleichtert das Einrichten komplizierter Datenstrukturen als verknüpfte Listen und Bäume erheblich.

Art
pNextItem = ^ TLinkedListItem
TLinkedListItem = AufzeichnungsName: String; iValue: Integer; NextItem: pNextItem;
Ende
;

Die Idee hinter verknüpften Listen besteht darin, uns die Möglichkeit zu geben, die Adresse für das nächste verknüpfte Element in einer Liste in einem NextItem-Datensatzfeld zu speichern.

Zeiger auf Datensätze können beispielsweise auch verwendet werden, wenn benutzerdefinierte Daten für jedes Baumansichtselement gespeichert werden.

Verfahrens- und Methodenzeiger

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 ähneln Prozedurzeigern. Anstatt jedoch auf eigenständige Prozeduren zu verweisen, müssen sie auf Klassenmethoden verweisen.

Der Methodenzeiger ist ein Zeiger, der Informationen sowohl zum Namen als auch zum Objekt enthält, das aufgerufen wird.

Zeiger und Windows API

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 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 Zeichenfolgen, wenn wir Windows-API-Funktionen aufrufen.

In vielen Fällen müssen diese Puffer und Datenstrukturen von der Anwendung zugewiesen werden, bevor ein API-Aufruf erfolgt, wenn ein API-Aufruf einen Wert in einem Puffer oder Zeiger auf eine Datenstruktur zurückgibt. Die Windows-API-Funktion SHBrowseForFolder ist ein Beispiel.

Zeiger- und Speicherzuordnung

Die wahre Stärke von Zeigern beruht auf der Fähigkeit, Speicher während der Ausführung des Programms zu reservieren.

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 (siehe oben)TextLen: Ganzzahl;
Start

{Holen Sie sich die Länge des Textes}
TextLen: = GetWindowTextLength (hWND);
{Speicher zuordnen}

GetMem (pText, TextLen); // nimmt einen Zeiger
{Holen Sie sich den Text des Steuerelements}
GetWindowText (hWND, pText, TextLen + 1);
{Text anzeigen}
ShowMessage (String (pText))
{Speicher freigeben}
FreeMem (pText);
Ende
;
instagram story viewer