Un punto de secuencia define cualquier punto en la ejecución de un programa informático en el que se garantiza que se habrán realizado todos los efectos secundarios de evaluaciones anteriores y que aún no se han realizado efectos secundarios de evaluaciones posteriores. A menudo se mencionan en referencia a C y C ++ , porque son un concepto central para determinar la validez y, si son válidos, los posibles resultados de las expresiones. A veces es necesario agregar más puntos de secuencia para definir una expresión y garantizar un único orden válido de evaluación.
Con C ++ 11 , el uso del término punto de secuencia ha sido reemplazado por secuenciación. Hay tres posibilidades: [1] [2] [3]
- La evaluación de una expresión se puede secuenciar antes que la de otra expresión o, de manera equivalente, la evaluación de la otra expresión se secuencia después de la primera.
- La evaluación de las expresiones tiene una secuencia indeterminada, lo que significa que una está secuenciada antes que la otra, pero que no está especificada.
- La evaluación de las expresiones no está secuenciada.
La ejecución de evaluaciones no secuenciadas puede superponerse, con un comportamiento indefinido catastrófico si comparten el estado . Esta situación puede surgir en cálculos paralelos , provocando condiciones de carrera . Sin embargo, ya puede surgir en situaciones simples no concurrentes como (a = 1) + (b = a)
, donde parte de la asignación a a
(por ejemplo, la mitad de los bits) puede ocurrir antes b = a
, y el resto después, de modo que después de la evaluación de la expresión, b
puede contener un significado sin sentido. estado intermedio de a
.
Ejemplos de ambigüedad
Considere dos funciones f()
y g()
. En C y C ++, el +
operador no está asociado con un punto de secuencia y, por lo tanto, en la expresión f()+g()
es posible que f()
o g()
se ejecute primero. El operador de coma introduce un punto de secuencia, y por lo tanto en el código f(),g()
se define el orden de evaluación: primero f()
se llama y luego g()
se llama.
Los puntos de secuencia también entran en juego cuando la misma variable se modifica más de una vez dentro de una sola expresión. Un ejemplo que se cita con frecuencia es la expresión Ci=i++
, que aparentemente asigna tanto i
su valor anterior como los incrementos i
. El valor final de i
es ambiguo porque, según el orden de evaluación de la expresión, el incremento puede ocurrir antes, después o intercalado con la asignación. La definición de un idioma en particular puede especificar uno de los posibles comportamientos o simplemente decir que el comportamiento no está definido . En C y C ++, la evaluación de una expresión de este tipo produce un comportamiento indefinido. [4] Otros lenguajes, como C # , definen la precedencia del operador de asignación e incremento de tal manera que i=i++
se garantiza el resultado de la expresión .
Puntos de secuencia en C y C ++
En C [5] y C ++, [6] los puntos de secuencia ocurren en los siguientes lugares. (En C ++, los operadores sobrecargados actúan como funciones y, por lo tanto, los operadores que se han sobrecargado introducen puntos de secuencia de la misma manera que las llamadas a funciones).
- Entre la evaluación de los operandos izquierdo y derecho de && ( AND lógico ), || ( OR lógico ) (como parte de la evaluación de cortocircuito ) y operadores de coma . Por ejemplo, en la expresión , todos los efectos secundarios de la subexpresión se completan antes de cualquier intento de acceso .
*p++ != 0 && *q++ != 0
*p++ != 0
q
- Entre la evaluación del primer operando del operador ternario "signo de interrogación" y el segundo o tercer operando. Por ejemplo, en la expresión hay un punto de secuencia después del primero , lo que significa que ya se ha incrementado cuando se ejecuta la segunda instancia.
a = (*p++) ? (*p++) : 0
*p++
- Al final de una expresión completa. Esta categoría incluye los estados de expresión (como la asignación ), declaraciones de retorno , las expresiones que controlan de , , , o - las declaraciones, y las tres expresiones en un comunicado.
a=b;
if
switch
while
do
while
for
- Antes de que se ingrese una función en una llamada de función. No se especifica el orden en el que se evalúan los argumentos, pero este punto de secuencia significa que todos sus efectos secundarios están completos antes de que se ingrese la función. En la expresión , se llama con un parámetro del valor original de , pero se incrementa antes de ingresar al cuerpo de . Del mismo modo, y se actualizan antes de ingresar y respectivamente. Sin embargo, no se especifica en qué orden , , son ejecutadas, ni en qué orden , , se incrementa. Si el cuerpo de accede a las variables y , podría encontrar que ambas, ninguna o solo una de ellas se han incrementado. (La llamada de función es no un uso del operador de coma; el orden de evaluación para , y está especificado.)
f(i++) + g(j++) + h(k++)
f
i
i
f
j
k
g
h
f()
g()
h()
i
j
k
f
j
k
f(a,b,c)
a
b
c
- En un retorno de función, después de que el valor de retorno se copia en el contexto de llamada. (Este punto de secuencia solo se especifica en el estándar C ++; solo está presente implícitamente en C. [7] )
- Al final de un inicializador ; por ejemplo, después de la evaluación de
5
en la declaración .int a = 5;
- Entre cada declarador en cada secuencia de declaradores; por ejemplo, entre las dos evaluaciones de en . [8] (Este no es un ejemplo del operador de coma).
a++
int x = a++, y = a++
- Después de cada conversión asociada con un especificador de formato de entrada / salida. Por ejemplo, en la expresión , hay un punto de secuencia después de que se evalúa y antes de imprimir .
printf("foo %n %d", &a, 42)
%n
42
Referencias
- ^ "ISO / IEC 14882: 2011" . Consultado el 4 de julio de 2012 .
- ^ "Una alternativa más detallada a los puntos de secuencia (revisada) (WG21 / N2239 J16 / 07-0099)" . Consultado el 5 de julio de 2012 .
- ^ "Orden de evaluación" . Consultado el 14 de octubre de 2015 .
- ^ Cláusula 6.5 # 2 de laespecificación C99 : " Entre el punto de secuencia anterior y el siguiente, se modificará el valor almacenado de un objeto como máximo una vez mediante la evaluación de una expresión. Además, solo se accederá al valor anterior para determinar el valor a ser almacenado " .
- ^ El Anexo C de laespecificación C99 enumera las circunstancias bajo las cuales se puede asumir un punto de secuencia.
- ^ El estándar C ++ de 1998 enumera los puntos de secuencia para ese lenguaje en la sección 1.9, párrafos 16-18.
- ^ Norma C ++, ISO 14882: 2003, sección 1.9, nota al pie 11.
- ^ Norma C ++, ISO 14882: 2003, sección 8.3: " Cada declarador init en una declaración se analiza por separado como si estuviera en una declaración por sí mismo " .
enlaces externos
- Pregunta 3.8 de las preguntas frecuentes de comp.lang.c