2011-12-20 22 views
59

Estoy un poco confundido acerca de cómo el compilador de C# maneja los incrementos y decrementos previos y posteriores.C# confusiones de pre y post incremento

Cuando codificar el siguiente:

int x = 4; 
x = x++ + ++x; 

x tendrá el valor 10 después. Creo que esto se debe a que el preincremento establece x en 5, lo que lo convierte en 5+5 que evalúa a 10. Luego, el incremento posterior actualizará x a 6, pero este valor no se utilizará porque 10 se asignará a x.

Pero cuando el código I:

int x = 4; 
x = x-- - --x; 

continuación x será 2 después. ¿Alguien puede explicar por qué este es el caso?

+2

¡Gran pregunta! Y hemos aprendido que nunca escribir código, tiene que pensar en lo que podría hacer, pero qué haría. – RvdK

+15

Cualquiera que escriba un código como este debe sacarse y dispararse. No hay excusa para 'x = x ++ + ++ x;' ... alguna vez. –

+15

era solo una pregunta "académica" - nunca escribiría un código como este :-) – Schweder

Respuesta

46

x-- será de 4, pero habrá 3 en el momento de --x, por lo que terminará siendo 2, entonces tendrá

x = 4 - 2 

por cierto, el primer caso habrá x = 4 + 6

He aquí un pequeño ejemplo que imprima los valores para cada parte, tal vez de esta manera vas a entender mejor:

static void Main(string[] args) 
{ 
    int x = 4; 
    Console.WriteLine("x++: {0}", x++); //after this statement x = 5 
    Console.WriteLine("++x: {0}", ++x); 

    int y = 4; 
    Console.WriteLine("y--: {0}", y--); //after this statement y = 3 
    Console.WriteLine("--y: {0}", --y); 

    Console.ReadKey(); 
} 

esto imprime o ut

x++: 4 
++x: 6 
y--: 4 
--y: 2 
+3

Gracias por su respuesta, pensé que los post-y-pre-incrementos se ejecutan después/antes de la evaluación de la línea de código completa, pero se ejecutan después/antes de la evaluación de cada elemento en la expresión. – Schweder

+0

@Schweder, ligera corrección: los operadores se ejecutan después/antes de la evaluación de la variable a la que se han aplicado. No todos y cada uno de los términos en la expresión. – Amy

+2

@Inuyasha: corrección de su corrección: los operadores * siempre * se ejecutan * después de * la evaluación de la variable como variable. La diferencia entre los operadores pre y post es solo * el valor devuelto *, no * el orden en que se realizan las operaciones *. –

-1

creo que la explicación para el caso ++ + ++ está mal:

comando ........... valor de x

.... .............. sin definir

int x = 4 .......... 4

x ++ ........... .... 5 (primer summand es 4)

++ x ............... 6 (segundo sumando es 6)

x = summand1 + summand2 ..4 + 6 = 10

Análogo la explicación de la - - - caso es

comando ........... valor de x

.................. indefinido

int x = 4 .......... 4

x --............... 3 (subtactor es 4)

--x ............... 2 (sustraendo es 2)

x = restador-sustracción ..4-2 = 10

+0

No entendí tu respuesta en absoluto, lo siento. –

+0

@phresnel Corregí un par de errores en la respuesta. Básicamente dice lo mismo que la respuesta que aceptaste: en realidad estamos recibiendo 10 porque estamos agregando 4 y 6; 2 es la diferencia entre 4 y 2. – phoog

16

Vamos a echar un vistazo a la IL que se genera a partir de esa declaración

IL_0002: ldloc.0  

carga el valor de x en la pila. Stack => (4)

IL_0003: dup   

Duplica el elemento superior de la pila. Pila => (4, 4)

IL_0004: ldc.i4.1  

Presione 1 en la pila. Pila => (1, 4, 4)

IL_0005: sub   

Reste los dos valores superiores e inserte el resultado en la pila. Pila => (3, 4)

IL_0006: stloc.0  

tienda el valor más alto de la pila de nuevo a x. Pila => (4)

IL_0007: ldloc.0  

Cargue el valor de x en la pila. Pila => (3, 4)

IL_0008: ldc.i4.1  

cargar el valor 1 en la pila. Pila => (1, 3, 4)

IL_0009: sub   

Reste los dos. Pila => (2, 4)

IL_000A: dup   

duplicar el valor superior => (2, 2, 4)

IL_000B: stloc.0  

tienda el valor superior de nuevo a x. Stack => (2, 4)

IL_000C: sub  

Resta los dos valores superiores. Pila => (2)

IL_000D: stloc.0 

Almacene este valor en x. x == 2

2

En este ejemplo,

int x = 4; 
x = x++ + ++x; 

se puede romper como:

x = 4++; which is = 5 
x = 4 + ++5; which is 4 + 6 
x = 10 

Del mismo modo,

int x = 4; 
x = x-- - --x; 

Aquí,

x = 4--; which is = 3 
x = 4 - --3; which is 4 - 2 
x = 2 

Simplemente colocando puedes decir, reemplaza el valor actual de x, pero para cada ++ o - suma/resta un valor de x.

6

Lo más interesante es que obtendrá una respuesta completamente diferente con el compilador C++. Net.

int x = 4; 
x = x++ + ++x; // x = 11 
x = 4; 
x = x-- - --x; // x = -1 

Por supuesto, la diferencia en los resultados se determina por diferentes semántica - parece normal. Pero a pesar del entendimiento, el hecho de que dos compiladores de .net no se comporten de manera similar para tales cosas básicas también me confunde.

+2

En C++ (ninguna de las versiones de C++ que no son C++ de Microsoft), modificar una variable varias veces antes del final de la expresión completa produce un comportamiento indefinido. –

+4

Esto no tiene nada que ver con * parse *. Tiene que ver con la semántica permitida de los dos idiomas con respecto a los puntos de secuencia. –

8

Desde su comentario:

pensé que previas y posteriores incrementos se ejecutan después/antes de la evaluación de la línea de código completa - pero se ejecutan antes/después de la evaluación de cada elemento de la expresión.

Su malentendido es muy común. Tenga en cuenta que en algunos idiomas, como C, no se especifica cuando el efecto secundario se vuelve visible y por lo tanto es legal, pero no obligatorio, para que su declaración sea verdadera en C.

Este no es el caso en C#; en C# siempre se observan efectos secundarios de código en el lado izquierdo de una expresión a suceder antes de código en el lado derecho ejecuta (de un solo hilo; en escenarios de multiproceso todas las apuestas están apagados.)

Para una más detallada explicación de lo que los operadores de incremento que en C#, ver:

What is the difference between i++ and ++i?

Hay un gran número de enlaces adicionales allí a los artículos que he escrito sobre este tema a menudo mal entendido.

Cuestiones relacionadas