Punto di sequenza

Da Wikipedia, l'enciclopedia libera.
Vai alla navigazione Vai alla ricerca

Un punto di sequenza (sequence point) è un punto nell'esecuzione di un programma informatico nel quale è garantito il fatto che tutti gli effetti collaterali delle istruzioni precedenti siano stati realizzati e nessun effetto collaterale delle istruzioni seguenti sia stato realizzato. I punti di sequenza sono un concetto chiave in linguaggi come C e C++[1][2][3], nei quali sono importanti per determinare la validità di una certa istruzione. L'aggiunta di ulteriori punti di sequenza nel codice può essere necessaria, ad esempio, per rendere un'espressione ben definita e garantire l'unicità dell'ordine di valutazione delle operazioni in essa contenute.

In C++11 l'espressione sequence point è stata sostituita da sequencing. Date due espressioni, vi sono tre possibili casi di sequencing:[4][5][6]

  1. la valutazione di un'espressione può essere "sequenced before" rispetto ad un'altra espressione o, equivalentemente, l'altra espressione è "sequenced after".
  2. le espressioni sono "indeterminately sequenced", ovvero una delle due è "sequenced before" rispetto all'altra, ma l'ordine è indefinito.
  3. la valutazione è "unsequenced".

Mentre nel primo caso la semantica del programma è ben definita, gli altri due casi sono problematici. In particolare, la valutazione di espressioni unsequenced può sovrapporsi e, se le due espressioni dipendono da uno stato condiviso, il risultato è indefinito e può avere effetti catastrofici. Tale situazione è un problema che si può incontrare facilmente in calcolo parallelo (corsa critica), ma può verificarsi anche in programmi strettamente sequenziali. Ad esempio, nella valutazione dell'espressione (a = 1) + (b = a) parte dell'assegnamento a = 1 (es. metà dei bit) può essere completato prima di b = a e parte dopo, per cui al termine della valutazione b può contenere uno stato intermedio di a, totalmente privo di significato.

Esempi di ambiguità[modifica | modifica wikitesto]

Date due funzioni f() e g(), poiché in C e C++ l'operatore + non genera un punto di sequenza, nella valutazione di f()+g() non è possibile sapere a priori quale chiamata tra f() e g() verrà valutata per prima. Al contrario, l'operatore virgola introduce un punto di sequenza, per cui nella valutazione dell'espressione f(),g() la chiamata f() verrà sempre valutata (e i suoi effetti collaterali realizzati) prima della valutazione di g().

I punti di sequenza svolgono un ruolo importante nel definire il comportamento di espressioni che manipolano più volte una stessa variabile. Un esempio comune in C è l'espressione i=i++, che apparentemente assegna ad i il suo stesso valore ed incrementa la variabile i. In realtà il valore finale di i al termine della valutazione non è definito, poiché l'operatore di assegnamento non determina un punto di sequenza, per cui l'incremento potrebbe essere eseguito prima, durante, o dopo l'assegnamento.[7] Altri linguaggi possono avere regole diverse: per esempio il C# definisce la precedenza degli operatori di assegnamento e di incremento in modo tale da garantire che il risultato dell'espressione i=i++ sia corretto e ben definito.

Punti di sequenza in C e C++[modifica | modifica wikitesto]

In C[8] e C++,[9] punti di sequenza sono garantiti nei seguenti casi:

  1. Tra la valutazione degli operandi sinistro e destro degli operatori &&, || (come conseguenza della valutazione a corto circuito), e operatore virgola. Ad esempio, nella valutazione dell'espressione *p++ != 0 && *q++ != 0 tutti gli effetti collaterali dell'espressione *p++ != 0 sono completati prima di ogni tentativo di accedere alla variabile q.
  2. Tra la valutazione del primo operando di un operatore ternario ?: e i due rimanenti operandi. Ad esempio, nella valutazione dell'espressione a = (*p++) ? (*p++) : 0 c'è un punto di sequenza dopo il primo *p++ il che significa che l'incremento prescritto nel primo operando è stato già eseguito quando il secondo accesso a p dovesse avvenire.
  3. Al termine di un'espressione completa, ovvero un'espressione che non è parte di un'altra espressione. Questa categoria include expression statement (ad esempio l'istruzione di assegnamento a=b;), l'istruzione return, i costrutti di controllo dell'esecuzione tramite la valutazione di una condizione if, switch, while, e do-while, e tutte e tre le espressioni nel blocco di controllo di un ciclo for.
  4. Prima di eseguire il corpo di una funzione. L'ordine in cui gli argomenti sono valutati è indefinito, ma è garantito che tutti gli argomenti siano stati valutati (e gli effetti collaterali dovuti alla loro valutazione realizzati) prima di iniziare l'esecuzione del corpo della funzione. Ad esempio, nella valutazione dell'espressione f(i++) + g(j++) + h(k++), la funzione f è chiamata con un argomento il cui valore è uguale a i prima dell'incremento, ma la variabile i è stata già aumentata quando l'esecuzione del corpo di f ha inizio. Analogamente, j e k sono incrementate prima di valutare il corpo delle rispettive funzioni g e h. Tuttavia l'ordine in cui f(), g() e h() sono eseguite non è definito, né è definito l'ordine in cui sono eseguiti gli incrementi delle tre variabili i, j, k. Se il corpo di f dovesse accedere alle variabili j and k, potrebbe verificarsi che nessuna, solo una, o entrambe le variabili siano state già incrementate. È importante notare che le virgole che compaiono nella chiamata f(a,b,c) non sono istanze dell'operatore virgola, ma sono token che formano la sintassi della chiamata di funzione, e non introducono punti di sequenza, per cui l'ordine di valutazione degli argomenti non è definito.
  5. Al termine della valutazione di una chiamata di funzione, dopo che il valore di ritorno è stato copiato nel contesto chiamante. Tale punto di sequenza è specificato esplicitamente solo in C++; è presente solo implicitamente in C.[10]
  6. Al termine della valutazione di un inizializzatore, ad esempio dopo la valutazione di 5 nella dichiarazione int a = 5;.
  7. Tra i dichiaratori in una sequenza di dichiarazioni. Ad esempio, vi è un punto di sequenza tra le due consecutive valutazioni di a++ nell'istruzione code>int x = a++, y = a++.[11] È importante sottolineare che, anche in questo caso, la virgola è parte della sintassi della dichiarazione, non è un operatore virgola.
  8. Dopo ogni conversione associata ad un specificatore di formato di input/output. Ad esempio, nell'espressione printf("foo %n %d", &a, 42) è presente un punto di sequenza dopo la valutazione di %n e prima della stampa di 42.

In C++, gli operatori soggetti ad overloading si comportano come normali funzioni per quanto riguarda l'introduzione di punti di sequenza.

Note[modifica | modifica wikitesto]

  1. ^ (EN) C Order of evaluation, su cppreference.com. URL consultato il 7 febbraio 2022.
  2. ^ (EN) Punti di sequenza C, su docs.microsoft.com, Microsoft, 8 marzo 2021. URL consultato il 13 ottobre 2018.
  3. ^ (EN) Dan Saks, Sequence Points, su embedded.com, 1º luglio 2002. URL consultato l'8 febbraio 2022.
  4. ^ (EN) ISO/IEC 14882:2011, su iso.org. URL consultato il 4 luglio 2012.
  5. ^ (EN) A finer-grained alternative to sequence points (revised) (WG21/N2239 J16/07-0099), su open-std.org. URL consultato il 5 luglio 2012.
  6. ^ (EN) C++ Order of evaluation, su cppreference.com. URL consultato il 14 ottobre 2015.
  7. ^ (EN) Specifiche del C99, clausola 6.5#2: "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored."
  8. ^ L'allegato C della specifica C99 elenca le circostanze nelle quali si può assumere la presenza di un punto di sequenza.
  9. ^ Lo standard C++ 1998 elenca i punti di sequenza di tale linguaggio nella sezione 1.9, paragrafi 16–18.
  10. ^ C++ standard, ISO 14882:2003, sezione 1.9, nota 11.
  11. ^ (EN) C++ standard, ISO 14882:2003, sezione 8.3: "Each init-declarator in a declaration is analyzed separately as if it was in a declaration by itself."

Collegamenti esterni[modifica | modifica wikitesto]

  Portale Informatica: accedi alle voci di Wikipedia che trattano di informatica