2010-09-03 13 views
17

bien, estoy un poco avergonzado de hacer esta pregunta, pero sólo quiero estar seguro ...cortocircuito de evaluación y los efectos secundarios

Se sabe que C utiliza evaluación de cortocircuito en las expresiones booleanas:

int c = 0; 
if (c && func(c)) { /* whatever... */ } 

En ese ejemplo func(c) no se llama porque c evalúa a 0. Pero, ¿qué tal un ejemplo más sofisticado en el que los efectos secundarios de la comparación cambiarían la variable que se compara a continuación? De esta manera:

int c; /* this is not even initialized... */ 
if (canInitWithSomeValue(&c) && c == SOMETHING) { /*...*/ } 

Función canInitWithSomeValue vuelve verdadera y cambios en el valor del puntero, dados en caso de éxito. ¿Está garantizado que las comparaciones posteriores (c == SOMETHING en este ejemplo) utilizan el valor establecido por canInitWithSomeValue(&c)?

No importa qué tan pesadas optimizaciones utiliza el compilador?

+0

Creo que puede confundir la evaluación de cortocircuito y la optimización del compilador. En el primer ejemplo, el compilador optimizará toda esa declaración 'if', porque nunca se puede ejecutar. La evaluación de cortocircuito significaría que si tuviera 'if (func1() && func2()) {...}', y func1() evaluado a falso ** en tiempo de ejecución ** (es decir, no definidamente al compilar), entonces el código no debería verificar 'func2()' - el compilador debería haber creado el código máquina de modo que si 'func1()' es falso, 'func2()' no se llama. – Stephen

+0

Que 'int c = 0' estaba allí para indicar que' c' es igual a '0' en el momento de la comparación, me doy cuenta de que en un caso así de simple el compilador optimizaría todo el' if'. –

+0

Ah, me disculpo. Te malinterpreté Mis disculpas. – Stephen

Respuesta

23

¿Está garantizado que las comparaciones posteriores (c == ALGO en este ejemplo) usa el valor establecido por canInitWithSomeValue (& c)?

Sí. Debido a que hay un sequence point

entre la evaluación de los operandos izquierdo y derecho de la && (AND lógico), || (OR lógico), y operadores de coma. Por ejemplo, en la expresión *p++ != 0 && *q++ != 0, todos los efectos secundarios de la subexpresión * p ++! = 0 se completan antes de cualquier intento de acceder a q.


Un punto de secuencia define cualquier punto de la ejecución de un programa de ordenador en el que se garantiza que se han realizado todos los efectos secundarios de las evaluaciones anteriores, y sin embargo no se han realizado los efectos secundarios de las evaluaciones posteriores .

+0

excelente respuesta, gracias! –

5

Sí. Porque ambos operadores && y || también son algo llamado puntos de secuencia. Este último define cuándo deben completarse los efectos secundarios de una operación previa y cuáles de la siguiente no deberían haber comenzado.

1

La evaluación en la condición compuesta de la declaración if es estrictamente de izquierda a derecha. La única circunstancia bajo la cual la segunda prueba en su if se optimizaría es si el compilador puede determinar con 100% de certeza que la primera es idénticamente igual a falsa.

Cuestiones relacionadas