Differenze tra le versioni di "Strutture: dichiarazione ed uso"
Riga 511: | Riga 511: | ||
<BR>Quando Gambas al suo interno crea un Oggetto di tipo ''Struttura'', esso crea una Classe; pertanto, affinché Gambas non compia un doppio lavoro, al posto di una ''Struttura'' è meglio usare direttamente una Classe. | <BR>Quando Gambas al suo interno crea un Oggetto di tipo ''Struttura'', esso crea una Classe; pertanto, affinché Gambas non compia un doppio lavoro, al posto di una ''Struttura'' è meglio usare direttamente una Classe. | ||
− | [3] 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. | + | [3] 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. |
Versione delle 11:13, 10 gen 2021
La Struttura [nota 1] similmente al vettore (Array) aggrega due o più elementi. Però, mentre il vettore aggrega elementi del medesimo tipo (per esempio tutti valori di tipo Integer, o di tipo Byte, etc), la Struttura aggrega solitamente (ma non necessariamente) elementi di tipo diverso.
In Gambas3 la Struttura, analogamente ad un Oggetto, può essere considerata una Classe priva di Metodi e di Eventi, che, come nel C, definisce e si riserva una porzione di memoria. Più precisamente la Struttura in Gambas è semplicemente una Classe senza Proprietà, Metodi ed Eventi, ed essendo dichiarabile esclusivamente Pubblica, conseguentemente i suoi membri sono "Pubblici". [nota 2]
La Struttura, variabile strutturata di reminescenza del C, è un tipo derivato che aggrega elementi di tipo diverso. Ci si serve di essa, qualora si abbia necessità di utilizzare un'area riservata di memoria di tipi di dati non omogenei.
Indice
- 1 Dichiarazione di una Struttura
- 2 Dichiarazione e creazione delle variabili di tipo Struttura
- 3 Passaggio di una Struttura a una Funzione
- 4 Strutture contenenti Vettori e Matrici
- 5 Strutture che contengono altre Strutture
- 6 Variabili array di tipo "Struttura"
- 7 Strutture che contengono variabili vettoriali di tipo Struttura
- 8 Note
Dichiarazione di una Struttura
La Struttura va dichiarata sempre con la parola chiave Public:
Public Struct Nome_della_Struttura nome_membro1 As tipo nome_membro2 As tipo etc.... End Struct
laddove:
- Struct è la parola chiave che introduce alla dichiarazione della Struttura;
- Nome_della_Struttura è l'etichetta che attribuisce un nome alla dichiarazione della Struttura;
- nome_membro1 e nome_membro2 sono le variabili della Struttura destinate a ricevere ciascuna un valore in base base al proprio tipo di appartenza (Byte, Short, Integer, etc).
- tipo è il tipo di dati (Byte, Short, Integer, etc.), al quale il membro della Struttura appartiene.
La dichiarazione della Struttura termina sempre con le parole chiave: End Struct .
Esempio astratto
Mostriamo un esempio astratto, nel quale dichiariamo una Struttura con dei membri, che dovranno essere riempiti con dei valori. Tale Struttura avrà un proprio nome e farà da modello alle particolari variabili di tipo Struttura che saranno effettivamente utilizzate per contenere valori.
La Struttura modello avrà il nome: NomeStruttura, mentre la variabile del tipo di quella Struttura la chiameremo: variabileStruttura:
Public Struct NomeStruttura ' definiamo i membri della Struttura "modello". ' Questa Struttura si riserverà, occupandola, 8 byte di memoria in tutto: valore1 As Byte ' Occupa 1 byte + un altro in questo caso per l'allineamento (byte di indici 0 e 1) valore2 As Short ' Occupa 2 byte: da quello di indice 2 a quello di indice 3 valore3 as Integer ' Occupa 4 byte: da quello di indice 4 a quello di indice 7 End Struct ' Dichiariamo una variabile di tipo Struttura (composta a perfetta immagine della Struttura modello): Private variabileStruttura As New NomeStruttura Public Sub Main() ' La variabile di tipo "Struttura" può essere dichiarata, ovviamente, anche come variabile "locale" nelle sub-procedure con: ' Dim variabile_struttura As New NomeStruttura ' Attribuiamo un valore a ciascun membro della variabile di tipo Struttura: variabileStruttura.valore1 = 4 variabileStruttura.valore2 = 444 variabileStruttura.valore3 = 44444 ' Quindi operiamo con i valori contenuti dalla variabile "variabileStruttura", per esempio li facciamo mostrare in console: With variabileStruttura Print .valore1 Print .valore2 Print .valore3 End With End
Dichiarazione e creazione delle variabili di tipo Struttura
La dichiarazione e la creazione di una variabile di tipo Struttura può richiedere l'uso della parola-chiave New.
Con l'uso della parola-chiave "New " viene creato l'Oggetto (ossia la variabile) del tipo della Classe Struttura dichiarata dall'utente.
L'uso della parola-chiave New in fase di dichiarazione della variabile di tipo Struttura è richiesto, quando vi è l'assegnazione diretta di un dato ad uno o più membri della Struttura all'interno di una routine, e, quindi, anche quando si deve passare a una funzione una variabile di tipo Struttura.
Esempio:
Public Struct STRUTTURA b As Byte s As Short End Struct Public Sub Main() Dim sr As New STRUTTURA ' Assegnazione diretta di un valore a un membro nella routine: sr.s = 999 ' Passaggio per "indirizzo" della variabile di tipo Struttura ad una funzione: Prova(sr) Print sr.b End Private Function Prova(t as STRUTTURA) ' Assegnazione diretta di un valore a un membro nella routine della funzione: t.b = 99 End
Non è invece richiesto nella routine principale, quando alla variabile deve essere assegnata una Struttura quale ritorno di una Funzione, nella quale è stata creata.
Dunque non sarà necessaria la parola-chiave "New" in una routine principale, qualora la variabile del tipo della Struttura, dichiarata e creata in una Funzione o in una Procedura, venga restituita alla routine principale che ha invocato la Funzione o la Procedura.
Esempio:
Public Struct STRUTTURA b As Byte s As Short End Struct Public Sub Main() Dim sr As STRUTTURA ' Qui non serve la parola-chiave "New", perché la varibile Struttura sarà istanziata nella Funzione chiamata ! ' La Funzione invocata restituisce una Struttura istanziata nella Funzione medesima: sr = Prova(9, 199) Print sr.b Print sr.s End Private Function Prova(vlb As Byte, vlc As Short) As STRUTTURA ' La Funzione restituisce la Struttura Dim tt As New STRUTTURA ' Crea la variabile del tipo della Struttura dichiarata all'inizio (Struct "STRUTTURA") tt.b = vlb * 10 tt.s = vlc * 100 Return tt End
Passaggio di una Struttura a una Funzione
Una variabile di tipo Struttura può senz'altro essere passata (e ritornata) "per Valore" a una Funzione o a una Procedura; ma, poiché tale variabile è in sostanza un Puntatore, contenente l'indirizzo di memoria della Struttura, sarà più opportuno e più adeguato passarla "per Indirizzo" (analogamente a quanto avviene con gli array): [nota 3]
Public Struct STRUTTURA b As Byte c As Short End Struct Public Sub Main() Dim sr as New STRUTTURA sr.b = 10 sr.c = 100 Funzione(sr) ' La variabile di tipo Struttura viene passata per "Indirizzo" Print sr.b Print sr.c End Private Function Funzione(sra As STRUTTURA) sra.b *= 10 sra.c *= 10 End
Strutture contenenti Vettori e Matrici
Le Strutture possono essere costituite da membri di variabili vettoriali (Array) e Matrici.
Esempio:
Public Struct StrutturaModello arB[10] As Byte ' array monodimensionale annidato definito arI As Integer[] ' array monodimensionale non definito mt[10, 4] As Byte ' matrice End Struct Public Sub Form_Open() Dim variabileStruttura As New StrutturaModello Dim a, m As Byte variabileStruttura.arI = New Integer[] For a = 0 To 9 With variabileStruttura .arB[a] = a .arI.Add(a + a) For m = 0 To 3 .mt[a, m] = variabileStruttura.arI[a] + 70 Next End With Next With variabileStruttura For a = 0 To 9 Print .arB[a], Next Print Print For a = 0 To 9 Print .arI[a], Next Print Print For a = 0 To 9 For m = 0 To 3 Print .mt[a, m], Next Print Next End With End
Strutture che contengono altre Strutture
Le Strutture possono contenere, come proprio membro, altre Strutture. In tal caso la Struttura principale è chiamata "Struttura innestata", mentre quella richimata nel membro della Struttura principale è chiamata "Struttura innesto". Da tenere presente che è necessario dichiarare e definire la Struttura "innesto", che sarà contenuta nella Struttura principale, prima della dichiarazione della Struttura principale contenente.
Esempio:
' Va dichiarata e definita innanzitutto la Struttura "innesto" che sarà contenuta nella Struttura principale: Public Struct strutturaInnesto sb As Byte sI As Integer s$ As String End Struct ' ...poi va dichiarata la Struttura principale "innestata", ossia quella che conterrà la Struttura "innesto". ' In un suo membro verrà dichiarata la variabile di tipo della Struttura "innesto" (che si intende appunto contenere in quella principale): Public Struct StrutturaPrincipale prB As Byte prI As Integer innestoStru As Struct strutturaInnesto ' oppure più semplicemente: innestoStru As strutturaInnesto End Struct Public Sub Main() Dim struttVariab As New StrutturaPrincipale Dim a As Byte a = 1 ' Assegnamo i valori alle variabili contenute nei membri della variabile Struttura principale: With struttVariab .prB = 10 .prI = 1000 .innestoStru.sb = a .innestoStru.sI = struttVariab.prI + a .innestoStru.s$ = "prova " & Str(a) End With ' Mostra i risultati in console: With struttVariab Print .prB Print .prI Print .innestoStru.sb Print .innestoStru.sI Print .innestoStru.s$ End With End
Il risultato in console sarà:
10
1000
1
1001
prova 1
Variabili array di tipo "Struttura"
E' infine possibile realizzare variabili array di tipo "Struttura".
La dichiarazione di variabili vettoriali di tipo Struttura può avvenire:
- mediante la parola Struct. Tale dichiarazione è Statica;
- mediante la parola New. Tale dichiarazione è Dinamica.
Vettori di tipo Struttura con numero di elementi definito
Possiamo dichiarare e creare variabili array di tipo Struttura con numero di elementi definito.
Uso della parola-chiave "Struct"
Se, per dichiarare un array di Struttura, viene usata la parola-chiave "Struct", allora tale dichiarazione dovrà essere posta al di fuori delle routine.
La parola-chiave "Struct" può essere utilizzata solo con array di tipo Struttura annidato.
Public Struct strutturaModello prB As Byte prI As Integer End Struct ' Dichiariamo la variabile della Struttura come array con numero di elementi definito. Private strutturaVariabile[10] As Struct StrutturaModello Public Sub Main() Dim a As Byte ' Assegnamo i valori agli elementi della variabile array di tipo Struttura: For a = 0 To 9 With strutturaVariabile[a] .prB = a .prI = 1000 + a End With Next ' Andiamo a mostrare i risultati in console: For a = 0 To 9 With strutturaVariabile[a] Print .prB Print .prI End With Next End
Uso della parola-chiave "New"
Se, per dichiarare un array di Struttura, si usa la parola-chiave "New", la dichiarazione potrà essere posta a seconda delle esigenze sia all'interno (per una variabile array "locale") che all'esterno (per una variabile array "Globale") delle routine.
Public Struct strutturaModello prB As Byte prI As Integer End Struct Public Sub Main() Dim a As Byte ' Dichiariamo la variabile della Struttura come array con numero di elementi definito. Dim strutturaVariabile As New StrutturaModello[10] ' Assegnamo i valori agli elementi della variabile array di tipo Struttura: For a = 0 To 9 With strutturaVariabile[a] = New StrutturaModello .prB = a .prI = 1000 + a End With Next ' Andiamo a mostrare i risultati in console: For a = 0 To 9 With strutturaVariabile[a] Print .prB Print .prI End With Next End
Vettori con numero di elementi indefinito
E' possibile creare una variabile array di tipo Struttura avente numero di elementi non predefinito. Si potranno quindi aggiungere gli elementi alla variabile vettore ogni qual volta le si attribuisce una semplice variabile di tipo Struttura.
Poiché, come si è avuto modo già di precisare, la dichiarazione di un vettore di tipo Struttura mediante la parola New conferisce dinamicità alla variabile vettoriale medesima, si farà uso di tale parola per consentire l'incremento degli elementi della variabile vettoriale di tipo Struttura.
Esempio:
Public Struct strutturaModello prB As Byte prI As Integer End Struct Public Sub Main() ' Dichiariamo la variabile della Struttura come array con numero di elementi indefinito. ' In questo caso sarà necessario inserire dopo "As" la parola "New", poiché creiamo un Oggetto array del tipo della Struttura: Dim prima As New StrutturaModello[] Dim a As Byte ' Dichiariamo un'altra variabile del tipo della Struttura modello: Dim seconda As StrutturaModello ' Assegnamo i valori agli elementi della variabile normale di tipo Struttura: For a = 0 To 9 ' Va prevista ovviamente la creazione di ogni variabile di tipo Struttura: seconda = New StrutturaModello With seconda .prB = a .prI = 1000 + a End With ' La variabile Struttura array vuole una variabile Struttura (non array) del tipo "StrutturaModello": prima.Add(seconda) Next ' Andiamo a mostrare i risultati in console: For a = 0 To 9 With prima[a] Print .prB Print .prI End With Next End
Strutture che contengono variabili vettoriali di tipo Struttura
Le Strutture possono contenere membri rappresentati da variabili vettoriali (array), o anche matrici, di tipo Struttura. Gli elementi di tali variabili vettoriali, o matrici, possono essere sia definiti che indefiniti, e dunque in quest'ultimo caso incrementabili nelle modalità viste nel paragrafo precedente.
In ogni caso la sintassi seguirà le forme viste in precedenza.
Variabile vettoriale di tipo Struttura con numero di elementi definito
Nel caso in cui la Struttura contenga uno o più membri rappresentati da variabili vettoriali di tipo Struttura con numero di elementi definito, si procederà nel seguente modo:
Public Struct Struttura_Secondaria a As Byte b As Integer End Struct ' Quindi la "Struttura" sarà rappresentata all'interno della Struttura principale ' dalla sua relativa variabile vettoriale, denominata "str_sec", usando le parole "As Struct": Public Struct Struttura_Principale primo_membro As Integer secondo_membro As Integer ' Dichiariamo mediante la parola "Struct" la variabile vettoriale di tipo della Struttura denominata "Struttura_Secondaria". ' La variabile vettoriale di tipo Struttura, membro di una Struttura principale e avente un numero definito di elementi deve essere "annidata". str_sec[n] As Struct Struttura_Secondaria End Struct
Esempio pratico
Public Struct Struttura_Secondaria a As Byte b As Integer End Struct Public Struct Struttura_Principale primo_membro As Integer secondo_membro As Integer str_sec[3] As Struct Struttura_Secondaria End Struct Public Sub Main() Dim sp As New Struttura_Principale sp.str_sec[0].a = 9 sp.str_sec[1].a = 10 Print sp.str_sec[0].a Print sp.str_sec[1].a End
Variabile vettoriale di tipo Struttura con numero di elementi indefinito
Nel caso in cui la Struttura contenga uno o più membri rappresentati da variabili vettoriali di tipo Struttura con numero di elementi non definito, si procederà nel seguente modo:
Public Struct Struttura_Secondaria a As Byte b As Integer End Struct ' Quindi la "Struttura" sarà rappresentata all'interno della Struttura principale dalla sua relativa variabile vettoriale, denominata "str_sec": Public Struct Struttura_Principale primo_membro As Integer secondo_membro As Integer ' Dichiariamo la variabile vettoriale di tipo della Struttura denominata "Struttura_Secondaria[]": str_sec As Struttura_Secondaria[] End Struct
Esempio pratico
Public Struct Struttura_Secondaria a As Byte b As Integer End Struct Public Struct Struttura_Principale primo_membro As Integer secondo_membro As Integer str_sec As Struttura_Secondaria[] End Struct Public Sub Main() Dim sp As New Struttura_Principale Dim ss As Struttura_Secondaria Dim i As Integer sp.str_sec = New Struttura_Secondaria[] For i = 1 To 8 With ss = New Struttura_Secondaria .a = i * 10 End With sp.str_sec.Push(ss) Next For i = 0 To 7 Print sp.str_sec[i].a, Next End
Note
[1] Vedasi anche la seguente sezione della Wiki: Strutture
[2] In ordine all'uso delle Strutture in Gambas, Minisini afferma che le Strutture esistono per permettere a Gambas di dialogare con le librerie C.
Quando Gambas al suo interno crea un Oggetto di tipo Struttura, esso crea una Classe; pertanto, affinché Gambas non compia un doppio lavoro, al posto di una Struttura è meglio usare direttamente una Classe.
[3] 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.