Skip to content

Assegnamento e Valutazione

In C, un operatore è un simbolo che esegue un’operazione su uno o più operandi. Un’espressione è una combinazione di operatori e operandi che produce un valore.

Quando esegui un assegnamento semplice come i = j;, il C fa una distinzione netta tra la parte sinistra e la parte destra:

  • lvalue (Locator Value): È l’operando di sinistra. Deve necessariamente rappresentare un oggetto in memoria (avere un indirizzo). Ad esempio, una variabile i o un elemento di un array arr[0].
  • rvalue (Right Value / Expression Value): È l’operando di destra. Può essere qualsiasi espressione che produce un valore, non ha bisogno di avere uno spazio allocato in memoria. Ad esempio 5, o i + 12.
int i = 5; // Corretto: 'i' è lvalue, '5' è rvalue
7 = i; // ERRORE: '7' è un rvalue, non ha una locazione di memoria!
int j = (i + 2); // Corretto: '(i + 2)' viene valutato come rvalue e salvato in 'j'

La valutazione di un’espressione fa due cose: calcola un valore e può produrre dei side effects (effetti collaterali). Scrivere un valore in una variabile, modificare un file o stampare a schermo sono tutti side effects.

int j;
j = printf("Ciao") + 9;
// Calcolo del valore: somma il numero di caratteri stampati (4) a 9.
// Side effect 1: stampa a schermo "Ciao".
// Side effect 2: aggiorna lo stato della memoria assegnando il totale a j.

L’ordine esatto in cui il C valuta i sotto-componenti di un’espressione è spesso non specificato (Unspecified Behavior). Se scrivi max(f(), g()), il compilatore è libero di chiamare prima f() oppure prima g().

Per mettere ordine, il C usa i Sequence Points (Punti di Sequenza). Un sequence point garantisce che tutti i side effects precedenti siano completati prima di proseguire la valutazione. Alla fine di un’istruzione completa (il ;) c’è sempre un sequence point.

Riscrivi l’istruzione in modo da eliminare l’Undefined Behavior e separare i side effects. Vogliamo incrementare la variabile i due volte e poi stamparne il quadrato.