Barninga Z
a- a+

Le variabili C register

L'ACCESSIBILITÀ' E LA DURATA DELLE VARIABILI

Le variabili register 

Dal momento che il compilatore colloca le variabili automatic nella RAM del calcolatore, i valori in esse contenuti devono spesso essere copiati nei registri della CPU per poter essere elaborati e, se modificati dall'elaborazione subita, copiati nuovamente nelle locazioni di memoria di provenienza. Tali operazioni sono svolte in modo trasparente per il programmatore, ma possono deteriorare notevolmente la performance di un programma, soprattutto se ripetute più e più volte (ad esempio all'interno di un ciclo con molte iterazioni). 

Dichiarando una variabile automatic con la parola chiave register si forza il compilatore ad allocarla direttamente in un registro della CPU, con notevole incremento di efficienza nell'elaborazione del valore in essa contenuto. Ecco un esempio: 

register int i = 10;

    do {
        printf("%2d
" ,i);
    } while(i--);

Il ciclo visualizza,  incolonnati[24], i numeri da 10 a 0; la variabile i si comporta come una qualsiasi variabile automatic, ma essendo probabilmente gestita in un registro consente un'elaborazione più veloce. E' d'obbligo scrivere "probabilmente gestita" in quanto non si può essere assolutamente certi che il compilatore collochi una variabile dichiarata con register proprio in un registro della CPU: in alcune situazioni potrebbe gestirla come una variabile automatic qualsiasi, allocandola in memoria. I principali motivi sono due: la variabile potrebbe occupare più byte di quanti compongono un registro della  CPU[25], o potrebbero non esserci  registri disponibili allo scopo[26]. 

Già che ci siamo, diamo un'occhiata più approfondita all'esempio di poco fa. Innanzitutto va rilevato che nella dichiarazione di i potrebbe essere omessa la parola chiave int

register i = 10;

Abbiamo poi utilizzato un costrutto nuovo: il ciclo do...while. Esso consente di identificare un blocco di codice (quello compreso tra le graffe) che viene eseguito finché la condizione specificata tra parentesi dopo la parola chiave while continua ad essere vera. Il ciclo viene sempre eseguito almeno una volta, perché il test è effettuato al termine del medesimo. Nel nostro caso, quale test viene effettuato? Dal momento che non è utilizzato alcun operatore di confronto esplicito, viene controllato se il risultato dell'espressione nelle tonde è diverso da 0. L'operatore --, detto di autodecremento, è specificato dopo la variabile a cui è applicato. Ciò assicura che i sia decrementata dopo l'effettuazione del test. Perciò il ciclo è eseguito 11 volte, con i che varia da 10 a 0 inclusi. Se l'espressione fosse --i, il decremento sarebbe eseguito prima del test, con la conseguenza che per i pari a 0 il ciclo non verrebbe più eseguito. 

Come per le variabili automatic, non è possibile conoscere il contenuto di una variabile register prima della sua esplicita inizializzazione mediante un operazione di assegnamento. In questo caso non si tratta di utilizzo e riutilizzo di un'area di memoria, ma di un registro macchina: non possiamo conoscerne a priori il contenuto nel momento in cui esso è destinato alla gestione della variabile (dichiarazione della variabile). Inoltre, analogamente alle variabili automatic, anche quelle register cessano di esistere all'uscita del blocco di codice (solitamente una funzione) nel quale sono dichiarate e il registro macchina viene utilizzato per altri scopi. 

Le variabili register, a differenza delle automatic, non hanno indirizzo: ciò appare ovvio se si pensa che i registri macchina si trovano nella CPU e non nella RAM. La conseguenza immediata è che una variabile register non può mai essere referenziata tramite un puntatore. Nel nostro esempio, il tentativo di assegnare ad un puntatore l'indirizzo di i provocherebbe accorate proteste da parte del compilatore. 

register i;
    int *iPtr = &i;        // errore! i non ha indirizzo

Pur non avendo indirizzo, le variabili register possono contenere un indirizzo, cioè un puntatore: la dichiarazione 

register char *ptr_1, char *ptr_2;

non solo è perfettamente lecita, ma anzi genera, se possibile, due puntatori (a carattere) particolarmente efficienti. 

 



Ti potrebbe interessare anche

commenta la notizia

C'è 1 commento
Francesco
Hai dubbi su questo articolo?