Differenza fra Assegnazione a un Puntatore di un indirizzo di memoria e Dereferenziazione di un Puntatore

Da Gambas-it.org - Wikipedia.

In questa pagina vedremo cosa significhi "Assegnare a un Puntatore un indirizzo di un'area allocata di memoria" e "Dereferenziare un Puntatore".

Assegnazione di un indirizzo di memoria a un Puntatore

La variabile di tipo "Puntatore" contiene un valore numerico che corrisponde all'indirizzo di memoria di un'altra variabile - ossia di un'area di memoria allocata automaticamente dal sistema sulla base dei tipi di dati nativi, fondamentali o derivati, previsti dal linguaggio di programmazione utilizzato - oppure con un numero arbitrario di byte da occupare stabilito dal codice.
Più in particolare il valore numerico, contenuto dalla variabile di tipo Puntatore, rappresenta l'indirizzo della cella di memoria ove è scritto il primo byte costituente il valore immagazzinato. In questo senso si dice che il Puntatore "punta" all'indirizzo, che esso contiene, di una cella di memoria.
Va detto che, finché il Puntatore resta semplicemente dichiarato e non istanziato (attraverso l'assegnamento), esso contiene un valore predefinito in Gambas uguale a 0 (zero); e pertanto esso non punta ad alcuna cella di memoria rilevante.

Assegnazione dell'indirizzo di memoria di una variabile fondamentale

Nel primo caso, descritto all'inizio di questo paragrafo, l'assegnamento al Puntatore dell'indirizzo di memoria di una variabile nativa fondamentale, già dichiarata, avviene con la funzione "VarPtr()".
Esempio:

Dim i As Integer = 1000
Dim p As Pointer

p = VarPtr(i)

Visivamente il puntamento alla cella di memoria della variabile di tipo "Integer" da parte del Puntatore dopo l'assegnamento dell'indirizzo di memoria è ad esempio il seguente:

il Puntatore "p" punta qui ------------------
indici indirizzi .... nnn0 nnn1 nnn2 nnn3 nnn4 nnn5 nnn6 nnn7 nnn8 nnn9 nn10 nn11 nn12 ....
dati-byte ....000000000000E8030000000000....
|______|
valore 1000
in little-endian

ossia nell'esempio il Puntatore "p" contiene il valore numerico dell'indirizzo della cella di memoria "nnn6".

Puntatore di Puntatore

Anche il Puntatore, essendo una variabile, può essere oggetto di assegnamento del suo indirizzo di memoria a un altro Puntatore.

p2 = VarPtr(p1)

Il secondo Puntatore in tal caso contiene l'indirizzo di memoria della prima variabile di tipo Puntatore e sarà chiamato "Puntatore di Puntatore".

Assegnazione dell'indirizzo di memoria di un'area di memoria allocata arbitrariamente

Nel secondo caso, descritto all'inizio di questo paragrafo, l'assegnazione dell'indirizzo di memria di un'area allocata, avente dimensioni stabilite arbitrariamente dal codice, avviene con la funzione "Alloc()".
Esempio:

Dim i As Integer
Dim p As Pointer

p = Alloc(SizeOf(gb.Byte), 8)

Assegnazione tra Puntatori

Ci può essere un terzo caso, in cui l'assegnazione di un indirizzo di memoria di un variabile o di un'area comunque allocata avviene tra Puntatori. [nota 1]
Esempio:

Dim p1, p2 As Pointer

p1 = VarPtr(i)

p2 = p1

oppure ad esempio nel caso di un vettore si può assegnare al Puntatore quanto ritornato dalla Proprietà ".Data" del vettore:

p = vettore.Data

In questo terzo caso va ricordato che "non" avviene una copia dei dati-byte presenti in un'area di memoria a un'altra, bensì il secondo Puntatore punterà anch'esso all'indirizzo di memoria puntato dal primo Puntatore.

Assegnazione diretta del valore numerico di un indirizzo di memoria

Va riportato, più che altro a scopo meramente didattico, che a una variabile di tipo Puntatore è possibile anche assegnare direttamente il valore numericodi un indirizzo di memoria (qualora lo si conosca), avendo cura di convertirlo preliminarmente in tipo di dato Long con la funzione "CLong()".
Un caso di uso può essere, quando dopo la deallocazione di un Puntatore, avvenuta automaticamente (se lo si è creato con la funzione "VarPtr()") oppure arbitrariamente mediante la funzione "Free()", si intenda assicurarsi che lo stesso Puntatore non punti ad alcun indirizzo di cella di memoria rilevante. In tal caso si riattribuisce al Puntatore, gia deallocato, il suo valore predefinito, ossia zero:

p = 0

Questo assegnamento diretto di un indirizzo di memoria a una variabile di tipo Puntatore è chiamato "Indirizzamento assoluto alla memoria ".

Si provi questo esempio:

Public Sub Main()

 Dim p As Pointer

 p = Alloc(SizeOf(gb.Integer), 1)
 Print "1 -> "; p

 Free(p)
 Print "2 -> "; p

 P = 0
 Print "3 -> "; p

End


Dereferenziazione di un Puntatore

Dereferenziare un Puntatore significa accedere all'area di memoria (variabile o area allocata arbitrariamente), da esso puntata, ed estrarre (leggere) i dati-byte immagazzinati in tale area.

La dereferenziazione può avvenire con le specifiche funzioni di dereferenziazione native di Gambas.
Esempio:

Dim i As Integer
Dim p As Pointer

i = 1000
p = VarPtr(i)

' Dereferenzia il "Puntatore" con la funzione "Int@()", giacché il tipo di dato della variabile, contenente il valore numerico "1000", è di tipo "Integer":
Print Int@(i)

Per dereferenziare un Puntatore di Puntatore si utilizza la funzione specifica "Pointer@()".


La dereferenziazione può avvenire anche con la risorsa "Memory Stream".
La risorsa "Memory Stream" crea una variabile di tipo "Stream" che rappresenta il flusso dei dati dell'area di memoria allocata e puntata dal Puntatore.
Pertanto con la risorsa "Memory Stream" si potranno leggere (ma anche scrivere) i dati-byte, contenuti nell'area di memoria, attraverso detta variabile di tipo "Stream".
Esempio:

Dim i, n As Integer
Dim p As Pointer
Dim st As Stream

i = 1000
p = VarPtr(i)

st = Memory p for Read
read #st, n
st.Close
Print n



Note

[1] Vedere anche la seguente pagina: Assegnare ad un Puntatore la rappresentazione numerica di un indirizzo di memoria contenuto da un altro Puntatore