2011-11-24 19 views
5

Recientemente se confundió por la siguiente C++ fragmento:Expresión orden de evaluación

#include <cstdio> 

int lol(int *k){ 
    *k +=5; 
    return *k; 
} 

int main(int argc, const char *argv[]){ 
    int k = 0; 
    int w = k + lol(&k); 
    printf("%d\n", w); 
    return 0; 
} 

Echa un vistazo a la línea:

int w = k + lol(&k); 

Hasta ahora yo pensaba que sería evaluado esta expresión de izquierda a derecha : tome el valor actual de k (que antes de llamar a la función lol es 0) y luego agréguelo al resultado de la función lol. Pero compilador me demuestra que estoy equivocado, el valor de w es 10. Incluso si cambio de lugares para que sea

int w = lol(&k) + k; 

el resultado sería todavía 10. ¿Qué estoy haciendo mal?

Tomek

+0

nada, '+' es la última operación – volody

Respuesta

3

Esto es porque los parámetros en una expresión son no especificado para ser evaluado en cualquier orden particular.

El compilador es libre de ejecutar cualquiera de los parámetros k o lol(&k) primero. No hay puntos de secuencia en esa expresión. Esto significa que los efectos secundarios de los parámetros se pueden ejecutar en cualquier orden.

Así que, en resumen, no se especifica si el código imprime 5 o 10. Ambas son salidas válidas.

La excepción a esto es el cortocircuito en expresiones booleanas porque && y || son puntos de secuencia. (ver comentarios)

+0

'&&', '||' y '?:', Que aparecen en expresiones, son puntos de secuencia. –

+0

@MarceloCantos: Gracias por ese poco de información. No estaba seguro del lenguaje exacto de los semantecs que hacían que las expresiones booleanas fueran diferentes. He aclarado mi respuesta. – Mysticial

+0

Tenga en cuenta que solo los puntos incorporados '&&' y '||' (y también ',') son secuenciales. Si están sobrecargados, se convierten en funciones de dos argumentos, y la orden de evaluación de los argumentos de la función no está especificada. –

2

Plus es por definición conmutativa, por lo que el orden en su ejemplo está totalmente definido por la implementación.

Mysticial es correcto al mencionar los puntos de secuencia. Citando Wikipedia article (no tienen estándar de C++ a mano):

Un punto secuencia en la programación imperativa define cualquier momento de la ejecución de un programa ordenador en el que se garantiza que todos los laterales efectos de las evaluaciones anteriores habrán sido realizado, y no se han realizado los efectos secundarios de evaluaciones posteriores. Son a menudo mencionados en referencia a C y C++, porque el resultado de algunas expresiones puede depender del orden de evaluación de sus subexpresiones . Agregar uno o más puntos de secuencia es un método de que garantiza un resultado consistente, porque esto restringe las posibles órdenes de evaluación .

El artículo también tiene una lista de puntos de secuencia en C++.

+0

"_su ejemplo está totalmente definido por la implementación._" No, no lo es. Ninguna implementación que yo sepa definir lo que sucede. – curiousguy

+0

@curiousguy: Tal vez, no me di cuenta. ¿Debo haber dicho "específico de la implementación" o "específico del compilador"? –

+0

o "dependiente de la implementación", o simplemente "no especificado". – curiousguy

3

Este código produce 5 o 10 dependiendo de la elección de evaluación de la llamada de función relativa a la del lado izquierdo de +.

Su comportamiento es no undefined porque una llamada de función está rodeada por dos puntos de secuencia.

Cuestiones relacionadas