Differenze tra le versioni di "Passaggio di un argomento per 'indirizzo' ad una Funzione"

Da Gambas-it.org - Wikipedia.
 
(7 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
Il passaggio come argomento ad una Funzione mediante un ''Puntatore'' dell'indirizzo di memoria di una variabile automatica ovvero di un'area di memoria appositamente allocata, viene definito "''passaggio per Indirizzo''". <SUP>&#91;[[#Note|Nota 1]]&#93;</sup>
+
Il passaggio come argomento ad una Funzione mediante un ''Puntatore'' dell'indirizzo di memoria di una variabile automatica ovvero di un'area di memoria appositamente allocata, viene definito "''passaggio per Indirizzo''". <SUP>&#91;[[#Note|Nota 1]]&#93;</sup> <SUP>&#91;[[#Note|Nota 2]]&#93;</sup>
<BR>Per passare l'<I>Indirizzo</i> di memoria di una variabile, bisognerà servirsi della funzione ''VarPtr( )''.
+
<BR>Per passare l'<I>Indirizzo</i> di memoria di una variabile, bisognerà servirsi della funzione "VarPtr()".
<BR>Per passare, invece, l'<I>Indirizzo</i> di memoria di un'area di memoria appositamente allocata mediante la funzione ''Alloc( )'', si passerà come argomento la variabile di tipo ''Puntatore'' che punta alla predetta area di memoria riservata.
+
<BR>Per passare, invece, l'<I>Indirizzo</i> di memoria di un'area di memoria appositamente allocata mediante la funzione "Alloc()", si passerà come argomento la variabile di tipo ''Puntatore'' che punta alla predetta area di memoria riservata.
  
Analogamente il passaggio per "''Indirizzo''" avviene anche usando i Vettori e le Strutture, poiché le relative variabili altro non sono che Puntatori alle aree di memoria di tali Oggetti.
+
Analogamente il passaggio per "''Indirizzo'' " avviene anche usando i "Vettori" e le "Strutture" (essendo le relative variabili nient'altro che Puntatori alle aree di memoria di tali Oggetti), nonché le variabili che identificano gli "Oggetti" quali istanze di Classi.
  
 
Il passaggio degli argomenti per ''indirizzo'' consente di eliminare l'istruzione ''Return'', e di ritornare, così, il valore dalla Funzione ''chiamata'' alla routine principale ''chiamante'' attraverso il parametro medesimo di tipo ''Puntatore'' della Funzione.
 
Il passaggio degli argomenti per ''indirizzo'' consente di eliminare l'istruzione ''Return'', e di ritornare, così, il valore dalla Funzione ''chiamata'' alla routine principale ''chiamante'' attraverso il parametro medesimo di tipo ''Puntatore'' della Funzione.
 +
<BR>Avere un riferimento all'oggetto è molto utile in fase di passaggio tramite parametri tra un Metodo e l'altro. La modifica dell'oggetto fa sì che venga mantenuta in uscita dal Metodo, eliminando così l'obbligo del ritorno di un valore.
  
E' appena il caso di ricordare che il passaggio di valori "''per Indirizzo''" a una sotto-procedura/funzione, non crea una copia dell'Oggetto, o comunque del tipo, passato, come avviene invece nel passaggio "''per Valore''", ove si va ad occupare un'altra area di memoria (per generare la copia) di dimensioni pari a quella occupata dall'Oggetto (o dal tipo di valore) passato.
+
E' appena il caso di ricordare che il passaggio di valori per "''Indirizzo'' " a una sotto-procedura/funzione, non crea una copia dell'Oggetto, o comunque del tipo, passato, come avviene invece nel passaggio per "''Valore'' ", ove si va ad occupare un'altra area di memoria (per generare la copia) di dimensioni pari a quella occupata dall'Oggetto (o dal tipo di valore) passato.
<BR>Va da sé che con il passaggio "''per Valore''", avendo due copie uguali, avremo due indirizzi di memoria che si riferiscono ovviamente a due aree di memoria riservate automaticamente di uguale dimensione, ...e quindi un consumo doppio delle risorse (ossia della memoria necessaria per il passaggio dei dati).
+
<BR>Va da sé che con il passaggio per "''Valore'' ", avendo due copie uguali, avremo due indirizzi di memoria che si riferiscono ovviamente a due aree di memoria riservate automaticamente di uguale dimensione, ...e quindi un consumo doppio delle risorse (ossia della memoria necessaria per il passaggio dei dati).
<BR>Il passaggio "''per Indirizzo''" fa in modo che la modifica avvenga direttamente all'indirizzo di memoria dell'Oggetto (o del tipo di valore) passato evitando così la creazione di una copia e l'occupazione di altra memoria per il medesimo dato da passare.
+
<BR>Il passaggio per "''Indirizzo'' " fa in modo che la modifica avvenga direttamente all'indirizzo di memoria dell'Oggetto (o del tipo di valore) passato evitando così la creazione di una copia e l'occupazione di altra memoria per il medesimo dato da passare.
  
Per scrivere in uno dei parametri di tipo ''Puntatore'' della Funzione chiamata il risultato finale delle operazioni compiute dalla Funzione medesima, bisognerà utilizzare - come sappiamo - i [[Definizione_ed_uso_dei_Memory_Stream|Memory Stream]]''.
+
Per scrivere in uno dei parametri di tipo ''Puntatore'' della Funzione chiamata il risultato finale delle operazioni compiute dalla Funzione medesima, bisognerà utilizzare - come sappiamo - i ''[[Definizione_ed_uso_dei_Memory_Stream|Memory Stream]]''.
  
  
 
===Passaggio per ''Indirizzo'' usando variabili di tipo ''Puntatore''===
 
===Passaggio per ''Indirizzo'' usando variabili di tipo ''Puntatore''===
Esempio di ''passaggio per Indirizzo'' dell'indirizzo di memoria di una variabile dichiarata come tipo ''Intero'', usando la funzione "''VarPtr( )''":
+
Esempio di ''passaggio per Indirizzo'' dell'indirizzo di memoria di una variabile dichiarata come tipo ''Intero'', usando la funzione "VarPtr()":
 
  '''Public''' Sub Main()
 
  '''Public''' Sub Main()
 
    
 
    
  Dim i As Integer
+
  Dim i As Integer
 
    
 
    
 
  <FONT Color=gray>' ''Assegnamo un valore iniziale alla variabile di tipo "Intero":''</font>
 
  <FONT Color=gray>' ''Assegnamo un valore iniziale alla variabile di tipo "Intero":''</font>
Riga 29: Riga 30:
 
    
 
    
 
  '''End'''
 
  '''End'''
 
 
   
 
   
 
  '''Private''' Function Funzione(p As Pointer)
 
  '''Private''' Function Funzione(p As Pointer)
Riga 36: Riga 36:
 
      
 
      
 
  <FONT Color=gray>' ''Otteniamo una variabile "Stream" dal "Puntatore" mediante i "Memory Stream":''</font>
 
  <FONT Color=gray>' ''Otteniamo una variabile "Stream" dal "Puntatore" mediante i "Memory Stream":''</font>
  st = Memory p For Write
+
  st = Memory p For Write
 
  <FONT Color=gray>' ''Scriviamo nel flusso dell'area di memoria, puntata dalla variabile "p", il risultato di una moltiplicazione:''</font>
 
  <FONT Color=gray>' ''Scriviamo nel flusso dell'area di memoria, puntata dalla variabile "p", il risultato di una moltiplicazione:''</font>
  Write #st, Int@(p) * 1000 As Integer
+
  Write #st, Int@(p) * 1000 As Integer
 
  <FONT Color=gray>' ''Chiudiamo il flusso di dati verso l'area di memoria:''</font>
 
  <FONT Color=gray>' ''Chiudiamo il flusso di dati verso l'area di memoria:''</font>
  st.Close
+
  st.Close
 
    
 
    
 
  '''End'''
 
  '''End'''
 
  
  
Riga 49: Riga 48:
 
  '''Public''' Sub Main()
 
  '''Public''' Sub Main()
 
    
 
    
  Dim p As Pointer
+
  Dim p As Pointer
 
    
 
    
 
  <FONT Color=gray>' ''Allochiamo un'area di memoria:''</font>
 
  <FONT Color=gray>' ''Allochiamo un'area di memoria:''</font>
Riga 60: Riga 59:
 
   Print Byte@(p)
 
   Print Byte@(p)
 
      
 
      
  <FONT Color=gray>' ''Liberiamo la memoria precedentemente allocata:''</font>
+
  <FONT Color=gray>' ''Libera la memoria precedentemente allocata e si assicura che il "Puntatore" non punti a un indirizzo di memoria rilevante:''</font>
 
   Free(p)
 
   Free(p)
 
 
<FONT Color=gray>' ''Ci assicuriamo che la variabile di tipo "Puntatore" non punti più ad alcuna cella di memoria:''</font>
 
 
   p = 0
 
   p = 0
 
    
 
    
 
  '''End'''
 
  '''End'''
 
 
   
 
   
 
  '''Private''' Function Funzione(po As Pointer)
 
  '''Private''' Function Funzione(po As Pointer)
 
    
 
    
  Dim st As Stream
+
  Dim st As Stream
 
+
 
  <FONT Color=gray>' ''Creiamo una variabile di tipo "Stream" mediante i "Memory Stream", al fine di poter scrivere all'interno dell'area di memoria allocata:''</font>
 
  <FONT Color=gray>' ''Creiamo una variabile di tipo "Stream" mediante i "Memory Stream", al fine di poter scrivere all'interno dell'area di memoria allocata:''</font>
 
   st = Memory po For Write
 
   st = Memory po For Write
Riga 80: Riga 76:
 
    
 
    
 
  <FONT Color=gray>' ''Chiudiamo il flusso di dati:''</font>
 
  <FONT Color=gray>' ''Chiudiamo il flusso di dati:''</font>
    st.Close
+
  st.Close
 
    
 
    
 
  '''End'''
 
  '''End'''
Riga 89: Riga 85:
 
   '''Public''' Sub Main()
 
   '''Public''' Sub Main()
 
    
 
    
  Dim vettore As New Integer[4]
+
  Dim vettore As New Integer[4]
  Dim i As Integer
+
  Dim i As Integer
 
+
 
   For i = 0 To vettore.Max
 
   For i = 0 To vettore.Max
 
       vettore[i] = i + 1
 
       vettore[i] = i + 1
Riga 103: Riga 99:
 
    
 
    
 
   '''End'''
 
   '''End'''
 
 
 
    
 
    
 
   '''Private''' Function Funzione(ii As Integer[])
 
   '''Private''' Function Funzione(ii As Integer[])
 
    
 
    
  Dim i As Integer
+
  Dim i As Integer
 
    
 
    
 
   For i = 0 To ii.Max
 
   For i = 0 To ii.Max
Riga 127: Riga 122:
 
   '''Public''' Sub Main()
 
   '''Public''' Sub Main()
 
    
 
    
  Dim stra As New STRUTTURA
+
  Dim stra As New STRUTTURA
 
    
 
    
 
   With stra
 
   With stra
Riga 144: Riga 139:
 
    
 
    
 
   '''End'''
 
   '''End'''
 
+
 
 
 
   '''Private''' Function Funzione(st As STRUTTURA)
 
   '''Private''' Function Funzione(st As STRUTTURA)
 
    
 
    
Riga 158: Riga 152:
  
  
 +
=Note=
 +
[1] In Gambas elementi complessi come gli ''Oggetti'' vengono sempre passati come ''Riferimento'', ovvero l'indirizzo di memoria in cui si trovano. Riguardo invece alle normali variabili di tipi base (Byte, Short, Integer/String/Long ecc.) queste non sono Oggetti ma "valori" ben precisi, che vengono passati come "Valore", e non come locazione di memoria. Questa differenza implica che, per quanto riguarda gli Oggetti, ogni modifica al suo contenuto viene mantenuta, mentre per le variabili, dato che ne viene passata una copia del valore, queste vengono perse all'uscita della stessa funzione che le gestisce.
 +
<BR>Il concetto di parametro passato "per Riferimento" (ByRif) in Gambas, fa sì che la funzione prende in ingresso l'indirizzo di memoria in cui è depositato il valore, e non ne crea una copia. Ciò consente, come per gli Oggetti, di ritrovarsi la variabile di base modificata anche dopo l'uscita dalla funzione.
  
=Note=
+
[2] Su questo argomento vedere anche la seguente pagina della WIKI:
[1] Su questo argomento vedere anche la seguente pagina della WIKI:
+
[http://www.gambas-it.org/wiki/index.php?title=Scrivere_una_Funzione#Passaggio_per_indirizzo Passaggio per indirizzo]
http://www.gambas-it.org/wiki/index.php?title=Scrivere_una_Funzione#Passaggio_per_indirizzo
 

Versione attuale delle 20:23, 1 ott 2022

Il passaggio come argomento ad una Funzione mediante un Puntatore dell'indirizzo di memoria di una variabile automatica ovvero di un'area di memoria appositamente allocata, viene definito "passaggio per Indirizzo". [Nota 1] [Nota 2]
Per passare l'Indirizzo di memoria di una variabile, bisognerà servirsi della funzione "VarPtr()".
Per passare, invece, l'Indirizzo di memoria di un'area di memoria appositamente allocata mediante la funzione "Alloc()", si passerà come argomento la variabile di tipo Puntatore che punta alla predetta area di memoria riservata.

Analogamente il passaggio per "Indirizzo " avviene anche usando i "Vettori" e le "Strutture" (essendo le relative variabili nient'altro che Puntatori alle aree di memoria di tali Oggetti), nonché le variabili che identificano gli "Oggetti" quali istanze di Classi.

Il passaggio degli argomenti per indirizzo consente di eliminare l'istruzione Return, e di ritornare, così, il valore dalla Funzione chiamata alla routine principale chiamante attraverso il parametro medesimo di tipo Puntatore della Funzione.
Avere un riferimento all'oggetto è molto utile in fase di passaggio tramite parametri tra un Metodo e l'altro. La modifica dell'oggetto fa sì che venga mantenuta in uscita dal Metodo, eliminando così l'obbligo del ritorno di un valore.

E' appena il caso di ricordare che il passaggio di valori per "Indirizzo " a una sotto-procedura/funzione, non crea una copia dell'Oggetto, o comunque del tipo, passato, come avviene invece nel passaggio per "Valore ", ove si va ad occupare un'altra area di memoria (per generare la copia) di dimensioni pari a quella occupata dall'Oggetto (o dal tipo di valore) passato.
Va da sé che con il passaggio per "Valore ", avendo due copie uguali, avremo due indirizzi di memoria che si riferiscono ovviamente a due aree di memoria riservate automaticamente di uguale dimensione, ...e quindi un consumo doppio delle risorse (ossia della memoria necessaria per il passaggio dei dati).
Il passaggio per "Indirizzo " fa in modo che la modifica avvenga direttamente all'indirizzo di memoria dell'Oggetto (o del tipo di valore) passato evitando così la creazione di una copia e l'occupazione di altra memoria per il medesimo dato da passare.

Per scrivere in uno dei parametri di tipo Puntatore della Funzione chiamata il risultato finale delle operazioni compiute dalla Funzione medesima, bisognerà utilizzare - come sappiamo - i Memory Stream.


Passaggio per Indirizzo usando variabili di tipo Puntatore

Esempio di passaggio per Indirizzo dell'indirizzo di memoria di una variabile dichiarata come tipo Intero, usando la funzione "VarPtr()":

Public Sub Main()
 
  Dim i As Integer
 
' Assegnamo un valore iniziale alla variabile di tipo "Intero":
  i = 1000
   
' Passiamo mediante la funzione "VarPtr()" l'indirizzo di memoria della variabile di tipo "Intero":
  Funzione(VarPtr(i))
   
  Print i
  
End

Private Function Funzione(p As Pointer)
 
 Dim st As Stream
    
' Otteniamo una variabile "Stream" dal "Puntatore" mediante i "Memory Stream":
 st = Memory p For Write
' Scriviamo nel flusso dell'area di memoria, puntata dalla variabile "p", il risultato di una moltiplicazione:
 Write #st, Int@(p) * 1000 As Integer
' Chiudiamo il flusso di dati verso l'area di memoria:
 st.Close
 
End


Esempio di passaggio per Indirizzo di una variabile di tipo Puntatore che punta ad una piccola area di memoria opportunamente allocata con la funzione "Alloc()":

Public Sub Main()
 
  Dim p As Pointer
 
' Allochiamo un'area di memoria:
  p = Alloc(SizeOf(gb.Byte), 2)
   
' Passiamo la viariabile di tipo "Puntatore" alla Funzione secondaria:
  Funzione(p)
   
' Dereferenziamo il "Puntatore", per vedere il valore presente nel primo byte dell'area riservata puntata:
  Print Byte@(p)
   
' Libera la memoria precedentemente allocata e si assicura che il "Puntatore" non punti a un indirizzo di memoria rilevante:
  Free(p)
  p = 0
  
End

Private Function Funzione(po As Pointer)
 
  Dim st As Stream

' Creiamo una variabile di tipo "Stream" mediante i "Memory Stream", al fine di poter scrivere all'interno dell'area di memoria allocata:
  st = Memory po For Write
  
' Scriviamo un valore di tipo "Byte" nel primo byte dell'area di memoria allocata:
  Write #st, 199 As Byte
  
' Chiudiamo il flusso di dati:
  st.Close
  
End


Passaggio per Indirizzo usando variabili di tipo vettoriale

Di seguito un semplice esempio usando un vettore, adeguatamente creato nella funzione principale chiamante:

 Public Sub Main()
 
  Dim vettore As New Integer[4]
  Dim i As Integer

  For i = 0 To vettore.Max
     vettore[i] = i + 1
  Next
  
  Funzione(vettore)   ' Passaggio per "Indirizzo"
  
  For Each i in vettore
    Print i
  Next
  
 End
 
 Private Function Funzione(ii As Integer[])
  
  Dim i As Integer
 
  For i = 0 To ii.Max
     ii[i] = ii[i] * 100
  Next
  
 End


Passaggio per Indirizzo usando variabili di tipo Struttura

Di seguito un semplice esempio usando una variabile di tipo Struttura, adeguatamente creata nella funzione principale chiamante:

 Public Struct STRUTTURA
   b As Byte
   c As Short
   i As Integer
 End Struct
 
 
 Public Sub Main()
 
  Dim stra As New STRUTTURA
  
  With stra
    .b = 100
    .c = 2000
    .i = 30000
  End With
  
  Funzione(stra)   ' Passaggio per "Indirizzo"
  
  With stra
    Print .b
    Print .c
    Print .i
  End With
  
 End

 Private Function Funzione(st As STRUTTURA)
  
  With st
    .b = st.b * 2
    .c = st.c * 2
    .i = st.i * 2
  End With
  
 End


Note

[1] In Gambas elementi complessi come gli Oggetti vengono sempre passati come Riferimento, ovvero l'indirizzo di memoria in cui si trovano. Riguardo invece alle normali variabili di tipi base (Byte, Short, Integer/String/Long ecc.) queste non sono Oggetti ma "valori" ben precisi, che vengono passati come "Valore", e non come locazione di memoria. Questa differenza implica che, per quanto riguarda gli Oggetti, ogni modifica al suo contenuto viene mantenuta, mentre per le variabili, dato che ne viene passata una copia del valore, queste vengono perse all'uscita della stessa funzione che le gestisce.
Il concetto di parametro passato "per Riferimento" (ByRif) in Gambas, fa sì che la funzione prende in ingresso l'indirizzo di memoria in cui è depositato il valore, e non ne crea una copia. Ciò consente, come per gli Oggetti, di ritrovarsi la variabile di base modificata anche dopo l'uscita dalla funzione.

[2] Su questo argomento vedere anche la seguente pagina della WIKI: Passaggio per indirizzo