__________
/ char *a; \
\ a="Moo!" /
----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
Lo scopo delle variabili è quello di contenere dei valori che possono essere modificati durante l’esecuzione, pertanto dopo la prima valorizzazione della variabile (definizione della variabile) essa può essere rivalorizzata. In C ciò può avvenire con l’operatore di assegnamento = come in questo frammento di codice, ma non solo.
Al momento della dichiarazione la variabile è indefinita: infatti potrebbe contenere un qualsiasi valore corrispondente alla valorizzazione puramente casuale all’area di memoria che gli è stata assegnata; molti compilatori moderni valorizzano con zero le variabili al momento della definizione, comunque l’uso di una variabile dichiarata ma non definita è sempre e comunque un errore! Si tratta però di un errore formale; il compilatore potrebbe al più segnalare un warning riguardo l’uso scorretto della variabile ma l’eseguibile verrà creato e fornirà un risultato che potrebbe dipendere dagli standard a cui si conforma il compilatore e pertanto risultare completamente inatteso.
/* Dichiarazione della variabile a */
int a;
/* La variabile ora è dichiarata, ovvero gli è stato assegnato
un'area di memoria ma non è definita e quindi non è utilizzabile.
Per definirla eseguiamo un'assegnazione
*/
a = 0;
/* La variabile a ora è assegnato il valore 0 */
a = 1;
/* ad a ora è assegnato il valore 1 */
In particolare per una variabile di tipo numerico può essere valorizzata con il risultato di un’espressione aritmetica a partire dal valore di altre variabili:
int a, b;
a = 10;
/* adesso a vale 10 e b non è definita */
b = a + 2;
/* adesso a vale 10 e b vale 12 */
Come in tutti i linguaggi di programmazione, un costrutto del tipo
a = a + 5;
è perfettamente valido: l’espressione a destra del segno = viene valutata e il risultato è posto nella variabile a. Il suo effetto è incrementare di 5 la variabile; e quindi ad esempio:
int a;
a = 3;
/* ad a ora è assegnato il valore 3 */
a = a + 5;
/* ad a ora è assegnato il valore 8 */
Il fatto che la stessa variabile sia presente sia a destra che a sinistra dell’operatore = non crea equivoci, anzi questo tipo di operazione è molto frequente, al punto che è si utilizza una simbologia specifica per questo tipo di operazione:
/* Incremento a di 5 */
a += 5;
Questo tipo di abbreviazione permette di rendere più immediata la lettura del codice e almeno da principio era stata pensata per ridurre il numero di istruzioni macchina che venivano generate durante la compilazione ottenendo in questo modo un eseguibile di dimensioni più ridotte e più veloce. I compilatori moderni prevedono comunque già una serie di ottimizzazioni per cui questo tipo di scrittura potrebbe essere tranquillamente evitato, eppure risulta ampliamente utilizzato, cosi come:
a -= 5; /* decrementa a di 5 */
a *= 5; /* valorizza a con il prodotto a * 5 */
a /= 5; /* valorizza a con il quoziente della divisione di a per 5 */
/* e altri operatori che vedremo in seguito */
Un’ulteriore simbologia che è tipica di questo linguaggio è quella di preincremento o postincremento: i costrutti ++a e a++ hanno entrambi l’effetto di incrementare di una unità il valore della variabile a, ma con una sottile differenza:
#include <stdio.h>
void main()
{
int a = 3;
/* operatore di postincremento alla variabile a */
printf("%d\n",a++);
printf("%d\n",a);
}
L’output di questo programma è
3
4
ovvero il valore della variabile viene prima passato alla funzione printf e solo successivamente viene incrementato, per questo motivo la seconda printf stampa il valore incrementato. Sostituendo l’operatore di preincremento nel programma precedente avremo:
#include <stdio.h>
void main()
{
int a = 3;
/* operatore di preincremento alla variabile a */
printf("%d\n",++a);
printf("%d\n",a);
}
che fornirà un output del tipo:
4
4
ovvero la variabile sarà in primo luogo incrementata e successivamente passata alla funzione printf per essere inviata all’output.
Anche l’uso di questo costrutto è molto frequente e si preferisce alla sua versione estesa a = a + 1, anche per questa sua flessibilità, ma è chiaro che quando si usa bisogna avere bene chiara la differenza tra le due modalità di utilizzo.
La stessa simbologia può essere usata per decrementare una variabile ovvero --a e a-- la variabile a viene diminuita in entrambi i casi di una unità, ma nel primo caso questa operazione viene effettuata prima che essa venga utilizzata, nel secondo caso avviene dopo averla usata.