C Language Modifica di qualsiasi oggetto più di una volta tra due punti di sequenza


Esempio

int i = 42;
i = i++; /* Assignment changes variable, post-increment as well */
int a = i++ + i--;

Codice come questo spesso porta a speculazioni sul "valore risultante" di i . Piuttosto che specificare un risultato, tuttavia, gli standard C specificano che la valutazione di tale espressione produce un comportamento indefinito . Prima del C2011, lo standard ha formalizzato queste regole in termini di cosiddetti punti di sequenza :

Tra il punto di sequenza precedente e quello successivo, un oggetto scalare deve avere il suo valore memorizzato modificato al massimo una volta dalla valutazione di un'espressione. Inoltre, il valore precedente deve essere letto solo per determinare il valore da memorizzare.

(Standard C99, sezione 6.5, paragrafo 2)

Questo schema si è dimostrato un po 'troppo rozzo, con il risultato che alcune espressioni esibivano un comportamento indefinito rispetto al C99 che plausibilmente non dovrebbe fare. C2011 conserva punti di sequenza, ma introduce un approccio più sfumato a quest'area basato sul sequenziamento e una relazione che chiama "sequenziata prima":

Se un effetto collaterale su un oggetto scalare è ingiustificato rispetto a un effetto collaterale diverso sullo stesso oggetto scalare o un calcolo del valore che utilizza il valore dello stesso oggetto scalare, il comportamento non è definito. Se esistono più ordinamenti consentiti delle sottoespressioni di un'espressione, il comportamento non è definito se si verifica un effetto collaterale non eseguito in uno degli ordini.

(Standard C2011, sezione 6.5, paragrafo 2)

I dettagli completi della relazione "sequenziata prima" sono troppo lunghi per essere descritti qui, ma integrano i punti di sequenza anziché sostituirli, quindi hanno l'effetto di definire il comportamento per alcune valutazioni il cui comportamento precedentemente non era definito. In particolare, se c'è un punto di sequenza tra due valutazioni, allora quella prima del punto di sequenza è "sequenziata prima" di quella successiva.

L'esempio seguente ha un comportamento ben definito:

int i = 42;
i = (i++, i+42); /* The comma-operator creates a sequence point */

L'esempio seguente ha un comportamento non definito:

int i = 42;
printf("%d %d\n", i++, i++); /* commas as separator of function arguments are not comma-operators */

Come in ogni forma di comportamento non definito, l'osservazione del comportamento effettivo della valutazione di espressioni che violano le regole di sequenziamento non è informativa, se non in senso retrospettivo. Lo standard linguistico non fornisce alcuna base per prevedere che tali osservazioni siano predittive anche del comportamento futuro dello stesso programma.