__________
/ 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.