2010-12-12 8 views
8

tengo este códigoMensaje incremento pregunta

static void Main(string[] args) 
{ 
    int x = 20; 
    int y = 35; 
    x = y++ + x++; 
    y = ++y + ++x; 
    Console.WriteLine(x); 
    Console.WriteLine(y); 
    Console.ReadLine(); 
} 

que espera que la salida sea x = 57 ey = 94. Sin embargo, cuando se ejecuta me dio 56 y 93. Por alguna razón el cargo de la subasta el operador no se está ejecutando en la línea 3.

¿Esto se debe a que estamos asignando el resultado de expresar en la línea 3 a la x misma? ¿Hay otros escenarios en los que el operador de incremento posterior no resulte como se esperaba?

Gracias.

+3

Solo una pista: escenarios como este son mucho más fáciles de entender si coloca cada caso de prueba en una función separada. Verificar lo que sucede en la segunda asignación es innecesariamente difícil debido a la primera asignación. –

Respuesta

13
int x = 20; 
int y = 35; 
// x = y++ + x++; this is equivalent of 
tmp = 35 + 20; y++; x++; x = tmp; 
// so here we have x = 55; y = 36 
// y = ++y + ++x; 
y ++; // 37 
x ++; // 56; 
y = x + y; 
// so here we have y = 93, x = 56; 
+0

Gracias. Despeja mi duda. – stackoverflow

3

El orden de ejecución viene determinado por la precedencia y asociatividad del operador.

asignación es asociativo por la derecha, por lo

x = y + x++; 

se puede reescribir

t = y + x++; 
x = t; 

no pude encontrar una declaración muy clara por el hecho de que el ++ sucede antes de la =.
Pero el texto en § 14.2 del documento Ecma implica que el efecto secundario ocurre como parte de la evaluación de i++. En F(i) + G(i++) * H(i), se llama al H(i) con el nuevo valor de i.

+0

Sin embargo, tenga en cuenta que el orden de _evaluation_ no tiene que imponer un cierto orden de _execution_. – SoftMemes

+0

@Freed es correcto. El orden de ejecución * de los operadores * se determina por precedencia y asociatividad. El orden de * evaluación de subexpresiones * es de izquierda a derecha, siempre. –

+2

También observo que su afirmación sobre asignaciones es incorrecta si "x" es una expresión con un efecto secundario. Por ejemplo: M(). X = y + N(). X ++ NO es lo mismo que t = y + N(). X ++; M(). X = t; porque eso invierte el orden en que se llaman M y N. –

9

Las reglas en C# son extremadamente sencillas. Ellos son:

  • subexpresiones de una expresión se evalúan IZQUIERDA A DERECHA, punto, fin de la historia.
  • el efecto secundario de un operador de incremento ocurre cuando se evalúa al operador.

Así que en su caso, esto se desglosa así; Fingiré que estamos haciendo esto en C en lugar de C# para que las direcciones y las referencias sean más claras.

x = y++ + x++; 

Evaluar la dirección de x y almacenar eso.

t1 = &x; 

Evaluar la dirección de y.

t2 = &y; 

Evalúe el valor almacenado en la dirección que acaba de calcular. Eso es 35.

t3 = *t2; // 35 

El valor recién calculado es el valor de la expresión; es el valor antes de el incremento.

Agregue uno a ese valor.

t4 = t3 + 1; // 36 

Tienda 36 en la dirección. y ahora es 36.

*t2 = t4; // y = 36 

Ahora haga lo mismo para x ++:

t5 = &x; 
t6 = *t5;  // 20 
t7 = t6 + 1; // 21 
*t5 = t7;  // x = 21 

bien, ahora tenemos que hacer la adición:

t8 = t3 + t6; // 35 + 20 = 55 

y asignar esa dirección calculada en un principio:

*t1 = t8; // x = 55; 

Al final de esta declaración x tiene tenía tres valores 20, 21 y 55 años y ha tenido dos valores, 35 y 36. X es ahora 55 ey es ahora 36.

y = ++y + ++x; 

Ahora vamos a hacer lo mismo otra vez, pero esta vez se usan los valores después de la incrementos Seguir a lo largo:

t1 = &y; 
t2 = &y; 
t3 = *t2; // 36 
t4 = t3 + 1; // 37 
*t2 = t4; // y = 37; 
t5 = &x; 
t6 = *t5; // 55 
t7 = t6 + 1; // 56; 
*t5 = t7; // x = 56; 
t8 = t4 + t7; // 93 
*t1 = t8; // y = 93; 

Así que al final de esta declaración y ha tenido tres valores: 36, 37 y 93. X ha tenido dos valores: 55 y 56. Y es ahora 93 y X es ahora 56.

que esperaba que la salida sea x = 57 ey = 94.

¿Por qué es de esperar? Su expectativa era contraria a la especificación C#; Me interesaría saber por qué esperabas el resultado equivocado. ¿Cómo esperaba que se genere el código para esto? ¿Esperaba que los incrementos ocurrieran después de la tarea? ¿Por qué harían eso? El incremento ocurre cuando el valor del operador de incremento se evalúa, y obviamente tiene que suceder antes de la suma, que obviamente tiene que suceder antes de la asignación. Por lo tanto, el incremento no puede ocurrir después de la asignación.

Por alguna razón el operador después de la subasta no está siendo ejecutado en la línea 3.

¿Cómo diablos has llegado a esa conclusión? Te aseguro que sin duda se está ejecutando. Paso a paso por la ejecución en un depurador si no me crees.

+0

1+, de la boca del caballo ... – SoftMemes

+0

gracias por la respuesta detallada ... nuestra comprensión del incremento posterior fue incorrecta. x = y ++ + x ++; para nosotros significa x = y + x; y = y + 1; x = x + 1; De esta manera llegamos a 20 + 35; 35 + 1; 55 + 1; y dado que la última expresión estaba en x, la asumimos 56. – stackoverflow