Anche se i puntatori non sono così importanti in Delphi come lo sono in C o C ++, sono uno strumento così "di base" che quasi tutto ciò che riguarda la programmazione deve gestire i puntatori in qualche modo.
È per questo motivo che potresti leggere di come una stringa o un oggetto sia in realtà solo un puntatore o che un gestore di eventi come OnClick sia in realtà un puntatore a una procedura.
In poche parole, un puntatore è una variabile che contiene l'indirizzo di qualsiasi cosa in memoria.
Per concretizzare questa definizione, tenere presente che tutto ciò che viene utilizzato da un'applicazione viene archiviato da qualche parte nella memoria del computer. Poiché un puntatore contiene l'indirizzo di un'altra variabile, si dice che punti a quella variabile.
Il più delle volte, i puntatori in Delphi puntano a un tipo specifico:
var
iValue, j: numero intero; pIntValue: ^ intero;
inizioiValue: = 2001; pIntValue: = @iValue;… j: = pIntValue ^;
fine;
La sintassi per dichiarare un tipo di dati del puntatore utilizza a caret (^). Nel codice sopra, iValue è una variabile di tipo intero e pIntValue è un puntatore di tipo intero. Poiché un puntatore non è altro che un indirizzo in memoria, dobbiamo assegnargli la posizione (indirizzo) del valore memorizzato nella variabile intera iValue.
Il @ operatore restituisce l'indirizzo di una variabile (o una funzione o procedura come si vedrà di seguito). Equivalente all'operatore @ è Funzione addr. Si noti che il valore di pIntValue non è 2001.
In questo codice di esempio, pIntValue è un puntatore intero digitato. Un buon stile di programmazione è usare i puntatori digitati il più possibile. Il tipo di dati Pointer è un tipo di puntatore generico; rappresenta un puntatore a qualsiasi dato.
Si noti che quando "^" appare dopo una variabile del puntatore, fa riferimento al puntatore; vale a dire, restituisce il valore memorizzato all'indirizzo di memoria trattenuto dal puntatore. In questo esempio, la variabile j ha lo stesso valore di iValue. Potrebbe sembrare che questo non abbia scopo quando possiamo semplicemente assegnare iValue a j, ma questo pezzo di codice è alla base della maggior parte delle chiamate all'API Win.
I puntatori non assegnati sono pericolosi. Poiché i puntatori ci consentono di lavorare direttamente con la memoria del computer, se proviamo (per errore) a scrivere in una posizione protetta nella memoria, potremmo ottenere un errore di violazione dell'accesso. Questo è il motivo per cui dovremmo sempre inizializzare un puntatore a NIL.
NIL è una costante speciale che può essere assegnata a qualsiasi puntatore. Quando zero è assegnato a un puntatore, il puntatore non fa riferimento a nulla. Delphi presenta, ad esempio, un array dinamico vuoto o una stringa lunga come un puntatore zero.
I tipi fondamentali PAnsiChar e PWideChar rappresentano i puntatori ai valori AnsiChar e WideChar. Il PChar generico rappresenta un puntatore a una variabile Char.
Questi puntatori di caratteri vengono utilizzati per manipolare stringhe con terminazione null. Pensa a un PChar come a un puntatore a una stringa con terminazione nulla o all'array che ne rappresenta una.
Quando definiamo un record o un altro tipo di dati, è prassi comune anche definire un puntatore a quel tipo. Ciò semplifica la manipolazione di istanze del tipo senza copiare grandi blocchi di memoria.
La possibilità di disporre di puntatori a record (e array) semplifica notevolmente l'impostazione di strutture di dati complicate come elenchi e alberi collegati.
genere
pNextItem = ^ TLinkedListItem
TLinkedListItem = discosName: String; iValue: Integer; NextItem: pNextItem;
fine;
L'idea alla base degli elenchi collegati è di darci la possibilità di memorizzare l'indirizzo nell'elemento collegato successivo in un elenco all'interno di un campo record NextItem.
I puntatori ai record possono essere utilizzati anche per la memorizzazione di dati personalizzati per ogni elemento della vista ad albero, ad esempio.
Un altro importante concetto di puntatore in Delphi sono i puntatori di procedura e metodo.
I puntatori che puntano all'indirizzo di una procedura o di una funzione sono chiamati puntatori procedurali. I puntatori di metodo sono simili ai puntatori di procedura. Tuttavia, invece di indicare procedure autonome, devono puntare a metodi di classe.
Il puntatore al metodo è un puntatore che contiene informazioni sul nome e sull'oggetto che viene invocato.
L'uso più comune per i puntatori in Delphi è l'interfacciamento al codice C e C ++, che include l'accesso all'API di Windows.
Le funzioni dell'API di Windows utilizzano numerosi tipi di dati che potrebbero non essere familiari al programmatore Delphi. La maggior parte dei parametri nella chiamata delle funzioni API sono puntatori a un certo tipo di dati. Come detto sopra, usiamo stringhe con terminazione null in Delphi quando chiamiamo le funzioni API di Windows.
In molti casi, quando una chiamata API restituisce un valore in un buffer o puntatore a una struttura dati, questi buffer e strutture dati devono essere allocati dall'applicazione prima di effettuare la chiamata API. La funzione API Windows SHBrowseForFolder è un esempio.
Il vero potere dei puntatori deriva dalla capacità di mettere da parte la memoria mentre il programma è in esecuzione.
Questo pezzo di codice dovrebbe essere sufficiente per dimostrare che lavorare con i puntatori non è così difficile come potrebbe sembrare all'inizio. È usato per cambiare il testo (didascalia) del controllo con la maniglia fornita.
procedura GetTextFromHandle (hWND: THandle);
var pText: PChar; // un puntatore a char (vedi sopra)TextLen: intero;
inizio
ottieni la lunghezza del testoTextLen: = GetWindowTextLength (hWND);
memoria alocata
GetMem (pText, TextLen); // prende un puntatore
ottieni il testo del controlloGetWindowText (hWND, pText, TextLen + 1);
visualizza il testoShowMessage (String (pText))
libera la memoriaFreeMem (pText);
fine;