FreeBASIC – puntatore

Nel precedente articolo abbiamo parlato del contenitore array. Oggi faremo la conoscenza del puntatore.

Cominciamo con il darne una sintetica definizione:

Un puntatore è una variabile il cui valore rimanda ad uno specifico indirizzo di memoria.

Dichiarare un puntatore

È necessario che vi sia una diretta corrispondenza tra il tipo di dato del puntatore e il tipo di dato dell’elemento puntato.

La dichiarazione di un puntatore è simile a quella per una variabile con l’unica differenza che occorre inserire il suffisso pointer (o ptr).

Assegnare un indirizzo di memoria ad un puntatore

Per assegnare ad un puntatore l’indirizzo di memoria di un elemento si utilizza l’operatore @ (chiocciola) che sta per indirizzo di.

Accedere al dato dell’elemento puntato

Per accedere al dato dell’elemento puntato si utilizza l’operatore * (asterisco) che sta per valore di.

Esempio

dim altezza as integer = 180
dim puntatore_altezza as integer pointer = @altezza
*puntatore_altezza = 20
print "Il valore dell'altezza e': "; altezza

Questo esempio mostra chiaramente che:

Far riferimento direttamente alla variabile o al puntatore della variabile non fa alcuna differenza.

Manipolare gli indirizzi di memoria

Arrivati a questo punto è lecito porsi due domande:

  1. Ma che ce ne dobbiamo fare dei puntatori?
  2. Non sono sufficienti le variabili?

Il fatto è che in alcune circostanze può essere utile lavorare direttamente con gli indirizzi di memoria. Questo però è un argomento che rientra tra quelli avanzati e quindi ne parleremo più avanti. Un po’ di pazienza 😉

Sino a questo momento abbiamo sempre parlato dei tipi di dato standard, nel prossimo articolo inizieremo a lavorare con i tipi di dato definiti da noi.

FreeBASIC – array

Dopo aver imparato il concetto di variabile e il suo utilizzo, vediamo ora un nuovo costrutto tipico dei linguaggi di programmazione.

Immaginiamo di dover lavorare con decine o centinaia di valori tutti dello stesso tipo di dato standard o di un tipo di dato deninito da noi. Farlo dichiarando per ogni valore una variabile sarebbe un compito alquanto stancante. In questi casi si ricorre all’uso degli array.

Definizione

Possiamo quindi definire un array come un:

contenitore indicizzato – mono o multidimendionale – di elementi tutti dello stesso tipo.

Indice di un elemento

Per accedere in lettura o in scrittura ad uno specifico elemento di questo insieme, si ricorre al suo relativo indice che non è altro che un valore di tipo integer che identifica la posizione dell’elemento all’interno dell’array.

L’indice va racchiuso all’interno di due parentesi tonde:

'dimensiona un array di 3 valori stringa
dim array_semaforo(1 to 3) as string

'assegna i valori
array_semaforo(1) = "rosso"
array_semaforo(2) = "giallo"
array_semaforo(3) = "verde"

'stampa i valori dell'array
print "Il semaforo ha i seguenti colori:"
for i as integer = 1 to 3
  print array_semaforo(i)
next

Nota sul dimensionamento di un array

Se nella fase di dimensionamento di un array non viene specificato il limite inferiore, questo assumerà il valore di default 0 (zero).

Dimensione di un array

Un array ha quindi una dimensione rappresentata dal numero degli elementi che contiene. Questa dimensione può essere fissa o variabile. Questa particolarità discrimina quindi due diversi tipi di array:

  1. fixed-length arrays
  2. variable-length arrays

La dimensione di un array è data dalla differenza tra il valore massimo dell’indice, ovvero il limite superiore (upper bound), e il suo valore minimo, ovvero il limite inferiore (lower bound) + 1.

Per ottenere il limite superiore e quello inferiore possiamo utilizzare le seguenti due istruzioni:

limite_superiore = ubound(mio_array)
limite_inferiore = lbound(mio_array)

La dimensione del nostro array sarà quindi:

dimensione = ubound(mio_array) - lbound(mio_array) + 1

Indice valido

Un valore valido per l’indice di un array deve soddisfare questa caratteristica:

lower bound ≤ indice valido ≤ upper bound

Differenze tra gli array fissi e variabili

Gli array con dimensione fissa hanno una maggiore efficienza rispetto a quelli con dimensione variabile in quanto il compilatore assegna loro una porzione di memoria statica che è più velocemente accessibile della memoria dinamica.

È quindi proprio l’allocazione statica della memoria che rende la dimensione di un array immutabile.

Agli array con dimensione variabile, invece, il compilatore assegna dinamicamente la memoria necessaria durante la stessa esecuzione del programma (ovvero a run-time). È proprio l’allocazione dinamica della memoria che permette di ampliare o ridurre le dimensioni di un array a scapito però della efficienza di lavoro.

Quindi se dobbiamo creare un insieme di valori omogenei che sappiamo a priori non varieranno mai come numero di elementi, allora ci converrà scegliere un array di tipo fisso, altrimenti ne creeremo uno di tipo variabile.

Come creare un array di tipo fisso o di tipo variabile

Per creare un array di tipo fisso è necessario che i suoi limiti siano dichiarati attraverso delle costanti o dei letterali:

'creo un array di tipo fisso con 10 elementi
const limite_superiore = 10
dim array_fisso(1 to limite_superiore) as string

Per creare invece un array di tipo variabile possiamo in un caso dichiarare i suoi limiti attraverso delle variabili, oppure crearne uno vuoto e poi utilizzare l’istruzione redim per ridimensionarlo:

'I caso: creo un array di tipo variabile con 10 elementi
dim as integer lim_inf, lim_sup
lim_inf = 1
lim_sup = 10
dim array1(lim_inf to lim_sup) as string

'II caso: creo un array vuoto e poi lo ridimensiono
dim array2() as string
redim array2(1 to 10) 'non è necessario specificare il tipo

Nota: quando utilizziamo l’istruzione redim per ridimensionare gli array di tipo variabile non è necessario specificare di nuovo il tipo di dato degli elementi.

Il ridimensionamento di un array di tipo variabile causa la perdita dei dati contenuti precedentemente in esso. Per ovviare a questo occorre utilizzare l’istruzione preserve:

redim preserve array2(1 to 10)

Creare un array multidimensionale

Se abbiamo necessità di creare un array a più dimensioni non faremo altro che aggiungere nuovi limiti nella fase di creazione o di ridimensionamento.

Per esempio potremmo avere la necessità di rappresentare una tabella con 10 righe e 5 colonne:

dim mia_tabella(1 to 10, 1 to 5) as [type]

Bene. Ora che abbiamo imparato a lavorare con gli array, siamo pronti per fare la conoscenza nel prossimo articolo di un nuovo amico: il puntatore.

FreeBASIC – variabile

Nel precedente articolo abbiamo discusso del concetto informatico di costante e di come utilizzarla nel nostro codice.

È arrivato quindi il momento di parlare della variabile cominciando a darne una sintetica definizione:

Una variabile è una etichetta che rimanda a dei dati registrati in una qualsiasi porzione di memoria che possono essere modificati in qualsiasi momento.

Dichiarazione

La prima cosa da fare quando vogliamo utilizzare una variabile nel nostro codice è dichiararla attraverso l’istruzione dim:

dim mia_variabile as string

Occorre però fare attenzione che i nomi delle nostre variabili rispettino due semplici regole sintattiche:

  1. i nomi possono contenere soltanto lettere maiuscole o minuscole, numeri e il carattere _ (trattino basso, underscore);
  2. i nomi non devono contenere degli spazi.

Come abbiamo già avuto modo di vedere nell’articolo dedicato specificatamente alla dichiarazione, questa assegna uno specifico tipo alla nostra variabile; ciò comporta che dovremo utilizzarla in maniera coerente nel nostro codice: ovvero se abbiamo dichiarato che la variabile è di tipo testo (string), non potremo utilizzarla direttamente in una espressione aritmetica, a meno che non operiamo intenzionalmente una sua conversione.

Ambito di utilizzo

A seconda del punto dove dichiariamo una variabile nel codice che stiamo scrivendo, questa avrà un suo specifico ambito di utilizzo (in inglese scope) che potrà essere:

  • limitato ad una procedura (subroutine o funzione);
  • limitato ad un modulo;
  • oppure utilizzabile ovunque all’interno dei moduli che compongono il nostro programma utilizzando la parola-chiave shared.

Bene, arrivati a questo punto siamo pronti per fare la conoscenza nel prossimo articolo di un tipo di variabile molto speciale: il vettore/matrice (più comunemente noto con il termine inglese array).

FreeBASIC – costante

In questo articolo faremo la conoscenza delle costanti.

In determinate circostanze è molto utile nella programmazione ricorrere all’uso di una o più costanti.

Per esempio se in più punti del nostro codice dobbiamo utilizzare il valore del Pi greco, è bene definire una costante, non avrebbe senso infatti definire una variabile in quanto il Pi greco è una nota costante matematica:

const pi_greco = 3.14159 ''la dichiarazione del tipo è opzionale

Una volta definita una costante non sarà più possibile cambiarne il valore nel codice, pena l’incorrere in un errore in fase di compilazione.

La cosa bella delle costanti è che hanno un ambito globale (global scope): ovvero possiamo utilizzare il loro nome, e quindi il loro valore, anche tra moduli diversi dello stesso programma.

Ovviamente siamo liberi di definire costanti numeriche, booleane o stringa:

const sconto as integer = 20
const stato as boolean = true
const etichetta as string = "SCONTO"

Se non viene dichiarato esplicitamente il tipo di costante, questo viene comunque inferito dal compilatore.

Nel prossimo articolo parleremo delle variabili.