Buscar..


Observaciones

Norma Internacional ISO / IEC 9899: 201x Lenguajes de programación - C

El acceso a un objeto volátil, la modificación de un objeto, la modificación de un archivo o la llamada a una función que realiza cualquiera de estas operaciones son todos efectos secundarios , que son cambios en el estado del entorno de ejecución.

La presencia de un punto de secuencia entre la evaluación de las expresiones A y B implica que cada cálculo de valor y efecto secundario asociado con A se secuencia antes de cada cálculo de valor y efecto secundario asociado con B.

Aquí está la lista completa de puntos de secuencia del Anexo C del borrador de publicación en línea 2011 del estándar en lenguaje C:

Puntos de secuencia

1 Los siguientes son los puntos de secuencia descritos en 5.1.2.3:

  • Entre las evaluaciones del designador de función y los argumentos reales en una llamada de función y la llamada real. (6.5.2.2).
  • Entre las evaluaciones del primer y segundo operandos de los siguientes operadores: lógico AND && (6.5.13); OR lógico || (6.5.14); coma , (6.5.17).
  • ¿Entre las evaluaciones del primer operando del condicional ? : operador y cualquiera de los segundos y terceros operandos se evalúa (6.5.15).
  • El fin de un declarador completo: declaradores (6.7.6);
  • Entre la evaluación de una expresión completa y la siguiente expresión completa a evaluar. Las siguientes son expresiones completas: un inicializador que no forma parte de un literal compuesto (6.7.9); la expresión en una declaración de expresión (6.8.3); la expresión de control de una declaración de selección ( if o switch ) (6.8.4); la expresión de control de una sentencia while o do (6.8.5); cada una de las expresiones (opcionales) de una declaración for (6.8.5.3); la expresión (opcional) en una declaración de return (6.8.6.4).
  • Inmediatamente antes de que una función de biblioteca regrese (7.1.4).
  • Después de las acciones asociadas con cada especificador de conversión de función de entrada / salida con formato (7.21.6, 7.29.2).
  • Inmediatamente antes e inmediatamente después de cada llamada a una función de comparación, y también entre cualquier llamada a una función de comparación y cualquier movimiento de los objetos pasados ​​como argumentos a esa llamada (7.22.5).

Expresiones secuenciadas

Se secuencian las siguientes expresiones:

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

En todos los casos, la expresión a se evalúa completamente y todos los efectos secundarios se aplican antes de evaluar b o c . En el cuarto caso, solo uno de b o c será evaluado. En el último caso, b se evalúa completamente y todos los efectos secundarios se aplican antes de evaluar c .

En todos los casos, la evaluación de la expresión a se secuencia antes de las evaluaciones de b o c (alternativamente, las evaluaciones de b y c se secuencian después de la evaluación de a ).

Así, expresiones como

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

Tener un comportamiento bien definido.

Expresiones sin secuencia

C11

Las siguientes expresiones no tienen secuencia :

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

En los ejemplos anteriores, la expresión a puede evaluarse antes o después de la expresión b , b puede evaluarse antes de a , o incluso pueden entremezclarse si corresponden a varias instrucciones.

Una regla similar es válida para las llamadas a funciones:

f(a, b);

Aquí no sólo a y b son unsequenced (es decir, la , operador en una llamada de función no produce un punto de secuencia), sino también f , la expresión que determina la función que se va a llamar.

Los efectos secundarios pueden aplicarse inmediatamente después de la evaluación o diferirse hasta un punto posterior.

Expresiones como

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;

producirá un comportamiento indefinido porque

  • una modificación de un objeto y cualquier otro acceso a él debe ser secuenciado
  • el orden de evaluación y el orden en que se aplican los efectos secundarios 1 no se especifican.

1 Cualquier cambio en el estado del entorno de ejecución.

Expresiones en secuencia indeterminada

Las llamadas de función como f(a) siempre implican un punto de secuencia entre la evaluación de los argumentos y el designador (aquí f y a ) y la llamada real. Si dos de estas llamadas no se secuencian, las dos llamadas de función se secuencian de forma indeterminada, es decir, una se ejecuta antes que la otra, y el orden no se especifica.

unsigned counter = 0;

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

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

Esta modificación doble de counter implícita durante la evaluación de los argumentos de printf es válida, simplemente no sabemos cuál de las llamadas viene primero. Como el orden no está especificado, puede variar y no se puede depender de él. Así que la impresión podría ser:

el orden es 0 1

o

el orden es 1 0

La declaración análoga a la anterior sin llamada de función intermedia

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

tiene un comportamiento indefinido porque no hay un punto de secuencia entre las dos modificaciones del counter .



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow