Ricerca…


Osservazioni

Standard internazionale ISO / IEC 9899: 201x Linguaggi di programmazione - C

L'accesso a un oggetto volatile, la modifica di un oggetto, la modifica di un file o il richiamo di una funzione che esegue una di queste operazioni sono tutti effetti collaterali , che sono cambiamenti nello stato dell'ambiente di esecuzione.

La presenza di un punto di sequenza tra la valutazione delle espressioni A e B implica che ogni calcolo del valore ed effetto collaterale associato ad A viene sequenziato prima di ogni calcolo del valore ed effetto collaterale associato a B.

Ecco l'elenco completo dei punti di sequenza dell'allegato C della bozza di pre-pubblicazione online 2011 dello standard di lingua C:

Punti di sequenza

1 I seguenti sono i punti di sequenza descritti in 5.1.2.3:

  • Tra le valutazioni del designatore di funzioni e gli argomenti effettivi in ​​una chiamata di funzione e la chiamata effettiva. (6.5.2.2).
  • Tra le valutazioni del primo e del secondo operando dei seguenti operatori: AND logico && (6.5.13); OR logico || (6.5.14); comma , (6.5.17).
  • Tra le valutazioni del primo operando del condizionale ? : viene valutato l'operatore e il secondo e il terzo operando (6.5.15).
  • La fine di un dichiarante completo: dichiarators (6.7.6);
  • Tra la valutazione di un'espressione completa e la successiva espressione completa da valutare. Le seguenti sono espressioni complete: un inizializzatore che non fa parte di un letterale composto (6.7.9); l'espressione in un'espressione (6.8.3); l'espressione di controllo di una dichiarazione di selezione ( if o switch ) (6.8.4); l'espressione di controllo di un while o do statement (6.8.5); ciascuna delle espressioni (facoltative) di una dichiarazione for (6.8.5.3); l'espressione (facoltativa) in una dichiarazione di return (6.8.6.4).
  • Immediatamente prima che una funzione di libreria ritorni (7.1.4).
  • Dopo le azioni associate a ciascun identificatore di conversione della funzione di input / output formattato (7.21.6, 7.29.2).
  • Immediatamente prima e immediatamente dopo ogni chiamata a una funzione di confronto, e anche tra qualsiasi chiamata a una funzione di confronto e qualsiasi movimento degli oggetti passati come argomenti a quella chiamata (7.22.5).

Espressioni sequenziate

Le seguenti espressioni sono sequenziate :

a && b
a || b
a , b
a ? b : c
for ( a ; b ; c ) { ... }

In tutti i casi, l'espressione a viene valutata completamente e tutti gli effetti collaterali vengono applicati prima che sia valutato b o c . Nel quarto caso, verrà valutato solo uno di b o c . Nell'ultimo caso, b viene completamente valutato e tutti gli effetti collaterali vengono applicati prima che c venga valutata.

In tutti i casi, la valutazione dell'espressione a sequenziato prima le valutazioni di b o c (alternativamente, le valutazioni di b e c sono in sequenza dopo la valutazione di a ).

Quindi, espressioni come

x++ && x++
x++ ? x++ : y++ 
(x = f()) && x != 0
for ( x = 0; x < 10; x++ ) { ... }
y = (x++, x++);

avere un comportamento ben definito

Espressioni senza conseguenze

C11

Le seguenti espressioni non sono state seguite :

a + b;
a - b;
a * b;
a / b;
a % b;
a & b;
a | b;

Negli esempi precedenti, l'espressione a può essere valutata prima o dopo l'espressione b , b può essere valutata prima di a , o possono anche essere mescolati se corrispondono a più istruzioni.

Una regola simile vale per le chiamate di funzione:

f(a, b);

Qui non solo a e b sono non in sequenza (cioè la , operatore in una chiamata di funzione non produce un punto sequenza), ma anche f , l'espressione che determina la funzione che deve essere chiamato.

Gli effetti collaterali possono essere applicati immediatamente dopo la valutazione o posticipati fino a un momento successivo.

Espressioni come

x++ & x++;
f(x++, x++); /* the ',' in a function call is *not* the same as the comma operator */
x++ * x++;
a[i] = i++;

o

x++ & x;
f(x++, x);
x++ * x;
a[i++] = i;

produrrà un comportamento indefinito perché

  • una modifica di un oggetto e qualsiasi altro accesso ad essa deve essere sequenziata
  • l'ordine di valutazione e l'ordine in cui vengono applicati gli effetti collaterali 1 non è specificato.

1 Eventuali cambiamenti nello stato dell'ambiente di esecuzione.

Espressioni a sequenza indeterminata

Le chiamate di funzione come f(a) implicano sempre un punto di sequenza tra la valutazione degli argomenti e il designatore (qui f e a ) e la chiamata effettiva. Se due di tali chiamate vengono annullate, le due chiamate di funzione vengono sequenzialmente indeterminate, ovvero, una viene eseguita prima dell'altro e l'ordine non è specificato.

unsigned counter = 0;

unsingned account(void) {
   return counter++;
}

int main(void) {
   printf("the order is %u %u\n", account(), account());
}

Questa modifica implicita del counter durante la valutazione degli argomenti di printf è valida, semplicemente non sappiamo quale delle chiamate viene prima. Poiché l'ordine non è specificato, può variare e non può dipendere da. Quindi la stampa potrebbe essere:

l'ordine è 0 1

o

l'ordine è 1 0

L'affermazione analoga a quanto sopra senza chiamata di funzione intermedia

   printf("the order is %u %u\n", counter++, counter++); // undefined behavior

ha un comportamento indefinito perché non esiste un punto di sequenza tra le due modifiche del counter .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow