Le variabili

Le variabili sono delle locazioni di memoria a cui è stato assegnato un nome e un tipo.
Nell'assegnare i valori alle variabili, il compilatore del Free Pascal genera il codice macchina per spostare il valore verso la posizione di memoria riservata a questa variabile.
Dove questa variabile vienè immagazzinata dipende da dove è stata dichiarata :

Le variabili globali .

Vengono dichiarate in una UNIT o in un programma, ma non all'interno di una procedura o di una funzione.
Queste variabili sono immagazzinate in posizioni di memoria fisse e sono disponibili durante l'intero periodo di esecuzione del programma.

Le variabili locali .

Vengono dichiarate all'interno di una procedura o di una funzione.
Il loro valore è memorizzato nello stack di programma, cioè non a delle locazioni di memoria fisse.

Il compilatore del Free Pascal gestisce l'allocazione di queste locazioni di memoria in modo trasparente , anche se queste locazioni possono essere influenzate nella fase di dichiarazione.
Il compilatore del Free Pascal inoltre gestisce in modo trasparente la lettura e scrittura dei valori nelle variabili .
Ma persino questo può essere gestito esplicitamente dal programmatore quando utilizza le proprietà.
Le variabili devono essere dichiarate esplicitamente quando si ha la necessità di utilizzarle.
Non verrà allocata memoria prima che una variabile sia dichiarata.
Utilizzare un identificatore di variabile (per esempio, una variabile di loop) prima di averla dichiarata genererà un errore che verrà segnalato dal compilatore.

-

La dichiarazione

Le variabili devono essere dichiarate in una sezione per la dichiarazione variabili di una UNIT o di una procedura o di una funzione. Ciò significa che quelle che seguono sono dichiarazioni valide:

Var
 curterm1 : integer;
 curterm2 : integer; cvar;
 curterm3 : integer; cvar; external;
 curterm4 : integer; external name 'curterm3';
 curterm5 : integer; external 'libc' name 'curterm9';
 curterm6 : integer absolute curterm1;
 curterm7 : integer; cvar; export;
 curterm8 : integer; cvar; public;
 curterm9 : integer; export name 'me';
 curterm10 : integer; public name 'ma';
 curterm11 : integer = 1 ;

Le differenze fra queste dichiarazioni viene spiegata di seguito :

1. La prima forma (curterm1) definisce una variabile normale. Il compilatore gestisce tutto in modo autonomo.

2. La seconda forma (curterm2) dichiara una variabile normale, ma specifica che il nome assembler per questa variabile è uguale al nome della variabile come scritto nel sorgente.

3. La terza forma (curterm3) dichiara una variabile che e posizionata esternamente: il compilatore presupporrà che la memoria allocata per questa variabile sia posizionata altrove e che il nome assembler per questa locazione è specificato dal nome della variabile, come scritto nel sorgente.

4. La quarta forma è completamente equivalente alla terza , dichiara una variabile che è immagazzinata esternamente ed esplicitamente fornisce il nome assembler della locazione.
Se cvar non viene usato, il nome deve essere specificato.

5. La quinta forma è una variante della quarta forma , viene solo fornito il nome della libreria in cui la variabile viene specificata .

6. La sesta forma dichiara una variabile (curterm6) e dice al compilatore a che venga immagazzinata nella stessa posizione di un'altra variabile (curterm1)

7. La settima forma dichiara una variabile (curterm7) e dice al compilatore che l'etichetta assembler di questa variabile dovrebbe essere il nome della variabile (case sensitive) e deve essere resa pubblica.

8. L'ottava forma (curterm8) è equivalente alla settima: ' pubblic' è uno pseudonimo per ' export'.

9. La nona e decima forma sono equivalenti : specificano il nome assembler della variabile.

11.L'undicesima forma dichiara una variabile (curterm11) e la inizializza con un valore (1 nel caso sopra riportato).

Si noti che i nomi assembler devono essere unici.
Non è possibile dichiarare o esportare 2 variabili con lo stesso nome assembler.

-

La visibilià

Le variabili, come ogni identificatore , obbediscono alle regole generali di visibilita'.
In aggiunta , le variabili inizializzate sono inizializzate quando entrano nell'area di visibilità.
Le variabili globali sono inizializzate una volta sola , quando il programma viene avviato.
Le variabili locali sono inizializzate ogni volta che viene eseguita la procedura .
Si noti che il comportamento per le variabili locali è differente da quello di un costante locale.
Una costante locale si comporta come una variabile globale inizializzata .

-

Variabili Thread

Per un programma che usa i thread, le variabili possono essere realmente globali, cioè la stessa variabile per tutti i thread , oppure possono essere locali al thread: ovvero ogni thread ottiene una copia della variabile.
Le variabili locali (definite all'interno di una procedura) sono sempre locali al thread.
Le variabili globali sono normalmente le stesse per tutti i thread.
Una variabile globale può essere dichiarata locale al thread sostituendo la parola chiave 'var' all'inizio del blocco di dichiarazione delle variabili con la parola chiave 'Threadvar':

Threadvar
IOResult: Numero intero;

Se nessun thread viene usato, la variabile si comporta come variabile ordinaria.
Se i thread sono usati allora viene fatta una copia della variabile per ogni thread (incluso per il thread principale).
Si noti che la copia della variabile viene fatta con il valore originale della stessa e non con il valore della variabile al momento dell'avvio del thread .
Le variabili dichiarate con la parola chiave "Threadvars" dovrebbero essere usate con parsimonia siccome la loro lettura e scrittura usa un numero alto di risorse .
Se possibile sarebbe meglio utilizzare delle varibili locali in quanto sono sempre più veloci da elaborare .
Di default i thread nel Free Pascal non sono abilitati .
Per maggiori informazioni sull'uso dei thread leggere il manuale del Free Pascal "Programmers guide".

-

Le proprietà

In un blocco globale si possono definire delle proprietà , esattamente come possono essere definite in una classe.
La differenza è che una proprietà globale non ha bisogno di un'istanza di classe : cè solo un'istanza di questa proprieta'.
A parte questa differenza , una proprietà globale si comporta come una proprietà di una classe.
Gli specificatori di lettura/scrittura per le proprietà globali devono essere delle normali procedure , non dei metodi.
Il concetto di proprietà globale è specifico del Free Pascal e non esiste in Delfi.
Il concetto di proprietà globale può essere utilizzato per nasconderè la locazione di un valore, o per calcolarene al volo il valore, o per controllare i valori che vengono scritti nella proprieta'.
Quello che segue è un esempio:


{$mode objfpc}
unit testprop;
Interface
Function GetMyInt : Integer;
Procedure SetMyInt(Value : Integer);
Property
MyProp : Integer Read GetMyInt Write SetMyInt;
Implementation
Uses sysutils;
Var
   FMyInt : Integer;
   Function GetMyInt : Integer;
   begin
    Result:=FMyInt;
   end;
   Procedure SetMyInt(Value :Integer);
   begin
   If ((Value mod 2)=1) then
    Raise Exception.Create(MyProp can only contain even value);
    FMyInt:=Value;
   end;
end.

Gli specificatori di lettura/scrittura possono essere nascosti dichiarandoli in un'altra UNIT che deve essere indicata nella sezione USES della UNIT.
Questo può essere utilizzato per nascondere gli specificatori di lettura/scrittura di accesso ai programmatori, come se fossero in una sezione di un codice 'privatè di una classe (discusso sotto).
Partendo dall'esempio precedente :

{$mode objfpc}
unit testrw;
Interface
Function GetMyInt : Integer;
Procedure SetMyInt(Value : Integer);
Implementation
Uses sysutils;
Var
   FMyInt : Integer;

Function GetMyInt : Integer;
begin
   Result:=FMyInt;
end;

Procedure SetMyInt(Value : Integer);
begin
   If ((Value mod 2)=1) then
   Raise Exception.Create(Only even values are allowed);
   FMyInt:=Value;
end;
end.

La UNIT testprop :

{$mode objfpc}
unit testprop;
Interface
uses testrw;
Property
   MyProp : Integer Read GetMyInt Write SetMyInt;
Implementation
end.

-