Comportamiento del operador de incremento previo y posterior en C, C ++, Java y C #

DESCARGO DE RESPONSABILIDAD: Este no es un ejemplo del mundo real. Es solo una pregunta teórica sobre cómo funcionan estos idiomas.

¿Cuáles son exactamente las diferencias entre C / C ++, C # y Java cuando se trata de operadores de post incremento y pre incremento?

Esto es lo que obtengo con VC ++ 10, Java 1.6 y C # 4

int a = 2; int b = a++ + a++; int c = ++a + a++ + a++; +-----+------+------+----+ | C | C++ | Java | C# | +-----+-----+------+------+----+ | a | 7 | 7 | 7 | 7 | +-----+-----+------+------+----+ | b | 4 | 4 | 5 | 5 | +-----+-----+------+------+----+ | c | 15 | 15 | 16 | 16 | +-----+-----+------+------+----+ 

Java y C # evalúan expresiones de izquierda a derecha, y los efectos secundarios son visibles de inmediato .

En C ++, el orden de evaluación de las subexpresiones no está especificado, y modificar el mismo objeto dos veces sin un punto de secuencia intermedio es un comportamiento indefinido.

No tengo tiempo para escribir una descripción detallada de las diferencias entre C ++, C, C # y Java. Simplemente diré que el comportamiento C # de los operadores de incremento pre y post está completamente especificado (en escenarios de subproceso único; si desea conocer su atomicidad, garantías sobre observaciones de órdenes de lectura y escritura en modelos de memoria débil de múltiples procesadores y y así sucesivamente, estás solo para hacer esa investigación). No está completamente especificado en C y C ++; un comstackdor tiene amplia latitud para hacer lo que le plazca con la reordenación de los efectos secundarios. Nunca utilicé Java, así que no voy a aventurarme a adivinar qué hace Java.

Para obtener más información sobre qué C # debe leer, lea la especificación C #. Para una breve explicación, lea mi respuesta a esta pregunta:

¿Cuál es la diferencia entre i ++ y ++ i?

Para una toma aún más corta:

Las subexpresiones en una expresión C # se agrupan lógicamente por precedencia y asociatividad, y luego se evalúan de izquierda a derecha independientemente. (Entonces, por ejemplo, A () + B () * C () evalúa A (), luego B (), luego C (). El hecho de que la multiplicación “viene antes” de la sum es irrelevante; las subexpresiones siempre se evalúan de izquierda a derecha.)

Si la evaluación de una subexpresión causa un efecto secundario debido a una subexpresión pre o post incremento, el efecto secundario ocurre inmediatamente antes de que se produzca el resultado.

En C ++, este es un comportamiento indefinido, por lo que cualquier respuesta sería correcta. Consulte Comportamiento indefinido y puntos de secuencia para obtener más detalles.

No estoy seguro sobre otros idiomas, pero también esperaría que este código fuera incorrecto allí.

EDITAR:
Vea la respuesta de Eric Lippert sobre C #. Él refuta mi suposición sobre el comportamiento de C #.

En C ++ al menos este comportamiento indefinido. Citando el estándar de C ++:

Entre el punto de secuencia anterior y siguiente, un objeto escalar tendrá su valor almacenado modificado como máximo una vez por la evaluación de una expresión.

El modelo de memoria de Java garantiza el orden en que se realizan las cargas y las tiendas, por lo que debería aparecer igual en cualquier JVM (creo).

Parece que C ++ tiene el mismo orden de operaciones , pero una vez que lo usas dos veces en una línea, empiezas a toparte con otras cosas (Vlad está ahí). Si prueba otros comstackdores de C ++, es posible que encuentre respuestas diferentes.

Estoy seguro de que C # tiene el mismo orden de operaciones, pero supongo que tienen un modelo de memoria (como Java) que garantiza la coherencia, pero no tengo mucho conocimiento aquí.

Me gusta esta pregunta y encontré muy buenas explicaciones, pero solo quiero explicar esta pregunta por su valor de cómo se evalúa:

Solo hablaré sobre Java y C / C ++ ya que no tengo conocimiento sobre C #

Las declaraciones se evalúan de las siguientes maneras

En java

Declaración

|

Rastro

 int a= 2; a=2 int b= a++ + a++; a=2, a=3 here value of a=4 int c = ++a + a++ + a++; a=5, a=5, a=6 here value of a=7 

En C / C ++

Rastro de statement

 int a= 2; a=2 int b= a++ + a++; a=2, a=2 here value of a=4 int c = ++a + a++ + a++; a=5, a=5, a=5 here value of a=7 

En resumen, en Java la expresión va de izquierda a derecha, de modo que en la segunda “a” obtendrá un nuevo valor y en c / c ++ primero evaluará la expresión completa y luego incrementará todos los operandos de la statement.