C Language Modificar cualquier objeto más de una vez entre dos puntos de secuencia.


Ejemplo

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

Código como este a menudo conduce a especulaciones sobre el "valor resultante" de i . Sin embargo, en lugar de especificar un resultado, los estándares de C especifican que la evaluación de tal expresión produce un comportamiento indefinido . Antes de C2011, el estándar formalizó estas reglas en términos de los llamados puntos de secuencia :

Entre el punto de secuencia anterior y el siguiente, un objeto escalar tendrá su valor almacenado modificado a lo sumo una vez por la evaluación de una expresión. Además, el valor anterior se leerá solo para determinar el valor que se almacenará.

(Norma C99, sección 6.5, párrafo 2)

Ese esquema demostró ser un poco demasiado tosco, lo que dio como resultado que algunas expresiones mostraran un comportamiento indefinido con respecto a C99 que no deberían ser verosímiles. C2011 conserva los puntos de secuencia, pero introduce un enfoque más matizado en esta área basado en la secuenciación y una relación que llama "secuenciada antes":

Si un efecto secundario en un objeto escalar no tiene secuencia en relación con un efecto secundario diferente en el mismo objeto escalar o un cálculo de valor utilizando el valor del mismo objeto escalar, el comportamiento no está definido. Si hay varios ordenamientos permitidos de las subexpresiones de una expresión, el comportamiento no está definido si se produce un efecto secundario no secuenciado en cualquiera de los ordenamientos.

(Norma C2011, sección 6.5, párrafo 2)

Los detalles completos de la relación "secuenciada antes" son demasiado largos para describirlos aquí, pero complementan los puntos de la secuencia en lugar de suplantarlos, por lo que tienen el efecto de definir el comportamiento para algunas evaluaciones cuyo comportamiento no estaba definido previamente. En particular, si hay un punto de secuencia entre dos evaluaciones, entonces el que está antes del punto de secuencia está "secuenciado antes" de la siguiente.

El siguiente ejemplo tiene un comportamiento bien definido:

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

El siguiente ejemplo tiene un comportamiento indefinido:

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

Al igual que con cualquier forma de comportamiento indefinido, observar el comportamiento real de evaluar expresiones que violan las reglas de secuencia no es informativo, excepto en un sentido retrospectivo. El estándar de lenguaje no proporciona ninguna base para esperar que tales observaciones sean predictivas, incluso del comportamiento futuro del mismo programa.