Variabili di tipo Puntatore e loro dereferenziazione

Da Gambas-it.org - Wikipedia.

La dereferenziazione di una variabile di tipo Puntatore si ha quando si deve estrarre il valore contenuto nella variabile puntata da Puntatore (il più delle volte tale Puntatore viene passato da una funzione esterna); oppure uno o più valori contenuti in un'area di memoria riservata precedentemente allocata con la funzione "Alloc()". [nota 1]

"Dereferenziare" un Puntatore significa, dunque, accedere alla locazione di memoria da esso puntata, per ottenere il valore contenuto dalla variabile puntata dal Puntatore. La variabile di tipo Puntatore, infatti, restituisce l'indirizzo di memoria di una variabile - se è stata usata la funzione "VarPtr()" - oppure di una area di memoria allocata (riservata), se è stata utilizzata la funzione "Alloc()".
Il Puntatore, così, ci consente di accedere alla variabile puntata oppure all'area di memoria allocata, al fine di leggervi o scrivervi dati-byte.

Per "dereferenziare" il Puntatore è possibile usare:

  • i Memory-Stream in lettura (soprattutto se è stata utilizzata una zona riservata di memoria con la funzione "Alloc()", e l'indirizzo è stato passato alla variabile di tipo Puntatore da una funzione esterna richiamata con Extern);
  • più brevemente una specifica funzione di Gambas che restituisca il valore memorizzato all'indirizzo specificato dal Puntatore ("Int@()", "Byte@()", "Float@()" e le altre simili a seconda del tipo).


Dereferenziazione con i Memory Stream

Per fare questo esempio pratico, poniamo il caso che venga passata ad una sub-procedura una variabili di tipo Puntatore, che punta ad un'area di memoria precedentemente riservata con la funzione "Alloc()" e nella quale siano stati scritti quattro valori di tipo Byte.
Il Puntatore sarà così dereferenziato usando i Memory Stream:

Private Procedure Dereferenzia(p As Pointer)

 Dim j, b As Byte
 Dim st As Stream

' Generiamo la variabile di tipo "Stream" dal "Puntatore" che è stato passato con la chiamata della sub-procedura:
 st = Memory p For Read

' Vengono estratti, in questo esempio, 4 byte leggendo la variabile di tipo "Stream":
 For j = 0 To 3
   Read #st, b
   Print "---> ", b
 Next

' Chiudiamo il flusso:
 st.Close

End


Dereferenziazione con le specifiche funzioni "Byte@()", "Short@()", "Int@()", etc.

In questo semplice esempio il Puntatore sarà dereferenziato con le funzioni specifiche di Gambas. Faremo un confronto con il linguaggio C.

Public Sub Main()

 Dim i As Integer        ' int i;
 Dim p As Pointer        ' int *p;

 i = 9999                ' i = 9999;

' Assegnamo alla variabile di tipo "Puntatore" la variabile di tipo Intero "i".
' Il "Puntatore", così, punta alla variabile "i", accedendo all'area di memoria della variabile:
 p = VarPtr(i)           ' p = &i;

' Dereferenziamo il "Puntatore" mediante la funzione di Gambas "int@()":
 Print "i = "; Int@(p)   ' printf("%d\n", *p);

End

Quando l'area di memoria puntata contiene due o più dati, se ci si intende spostare all'interno di essa - senza voler utilizzare i Memory Stream -, si provvederà ad aggiungere all'indirizzo di memoria, contenuto dal Puntatore uno o più unità utili a raggiungere il primo dato-byte del valore da leggere.

Esempio:

Public Sub Main()

 Dim p As Pointer
 Dim st As Stream
 
 p = Alloc(SizeOf(gb.Byte), 8)
 st = Memory p For Write
 Write #st, 3333 As Short
 Write #st, 555555 As Integer
 st.Close

' Dereferenzia il "Puntatore" e legge i dati-byte (cominciando dall'indice 0 dell'area di memoria allocata) che costituiscono lo dato "Short", previsto sopra nel codice:
 Print Short@(p)

' Aggiunge due unità, per poter superare nel flusso di memoria i dati che costituiscono il tipo di dato "Short", così da raggiungere il primo dato-byte del dato "Integer":
 Print Int@(p + 2)
  
 Free(p)

End


Dereferenziare senza Memory-Stream un Puntatore ad una Struttura, passato da una funzione esterna

Per quest'argomento rimandiamo alla specifica pagina presente nella WIKI:
Dereferenziare senza Memory-Stream un Puntatore ad una Struttura, passato da una funzione esterna.


Note

[1] Se la variabile di tipo Puntatore deve puntare ad una variabile ad un tipo fondamentale (o meglio: contenere l'indirizzo di memoria di una variabile) già dichiarata, allora si userà la funzione "VarPtr()".
Se la variabile di tipo Puntatore deve essere utilizzata per creare un variabile di tipo Stream, nel quale successivamente scrivere dati, allora sarà opportuno allocare una parte di memoria mediante la funzione "Alloc()".