Cuál es la diferencia entre X = X ++; vs X ++ ;?

¿Alguna vez has intentado esto antes?

static void Main(string[] args) { int x = 10; x = x++; Console.WriteLine(x); } 

Salida: 10.

pero para

 static void Main(string[] args) { int x = 10; x++; Console.WriteLine(x); } 

Salida: 11.

¿Alguien podría explicar por qué esto?

X ++ incrementará el valor, pero luego devolverá su valor anterior.

Entonces en este caso:

 static void Main(string[] args) { int x = 10; x = x++; Console.WriteLine(x); } 

Usted tiene X en 11 solo por un momento, luego vuelve a 10 porque 10 es el valor de retorno de (x ++).

En su lugar, podría hacer esto por el mismo resultado:

 static int plusplus(ref int x) { int xOld = x; x++; return xOld; } static void Main(string[] args) { int x = 10; x = plusplus(x); Console.WriteLine(x); } 

También vale la pena mencionar que obtendría el resultado esperado de 11 si lo hubiera hecho:

 static void Main(string[] args) { int x = 10; x = ++x; Console.WriteLine(x); } 

En la asignación x = x++ primero se extrae el valor anterior de x para usar al evaluar la expresión del lado derecho, en este caso ‘x’; luego, incrementa x en 1. Por último, asigna los resultados de la evaluación de expresión (10) a x través de la statement de asignación.

Tal vez un código equivalente aclare la situación:

 var tmp = x; x++; x = tmp; 

Este es el equivalente de su código x = x++ en C #.

El comportamiento de x ++ es incrementar x pero devolver el valor antes del incremento. Se llama incremento de publicación por esta razón.

Entonces x = x ++; simplemente ponlo

1. devuelve el valor , luego

2. incremente x , luego

3. Asigne el valor original (devuelto en el paso 1) de x a x .

x = ++ x

equivaldría a 11.

 x++; 

hace lo siguiente:

 int returnValue = x; x = x+1; return returnValue; 

Como puede ver, el valor original se guarda, x se incrementa y luego se devuelve el valor original.

Lo que esto hace es guardar el valor 10 en alguna parte, establecer x igual a 11 y luego devolver 10, lo que hace que x vuelva a 10. Tenga en cuenta que x realmente se convierte en 11 durante unos pocos ciclos (suponiendo que no hay optimización del comstackdor) .

Esto no responde la pregunta directamente, pero ¿por qué en el mundo alguien usaría

 x = x++; 

?

Es totalmente contrario al propósito del operador de incremento / preinclusión.

Puedes pensarlo así:

 int x = 10; 

X es un contenedor, y contiene un valor, 10.

 x = x++; 

Esto puede ser desglosado para:

 1) increment the value contained in x now x contains 11 2) return the value that was contained in x before it was incremented that is 10 3) assign that value to x now, x contains 10 

Ahora, imprima el valor contenido en x

 Console.WriteLine(x); 

Y, como era de esperar, imprime 10.

Por definición, x ++, devuelve el valor de xy luego incrementa x.

http://blogs.msdn.com/lucabol/archive/2004/08/31/223580.aspx

Lo primero que haces se llama “post-incremento”, lo que significa que

  int x = 10; x++; //x still is 10 Console.WriteLine(x); //x is now 11(post increment) 

así que en el momento de asignar x = x ++; x todavía es 10 lo que podría hacer, si necesita que x sea 11 en esta línea, escriba ++ x (creo que se llama preincremento, corrígeme si estoy equivocado) … alternativamente, x = derecho; y que x = x ++;

pregunta, depende de la línea o de la statement, lo que significa que boostá después de; ?

Intenta llamar a ++ x y ver si funciona.

Colocar el operador de incremento después de la variable significa que el incremento y la asignación suceden después de que se evalúa la expresión … entonces La instrucción original x = x ++; se traduce en 1. Evaluar x y almacenar valor en la memoria de tránsitos … Ahora ejecute el código solicitado por el operador ++ …. (pasos 2 y 3) 2. Incremente el valor de x (en la memoria transitoria) 3. Asigne un valor incrementado a la ubicación de almacenamiento de x … Ahora, continúe con el rest de la ejecución de la línea, a la izquierda, hay un signo = … 5. Asigne el valor almacenado en el Paso 1 (valor no incrementado) a la expresión a la izquierda de = signo … . que es x

Quizás no estoy en lo correcto, pero es más fácil para mí entender el resultado en un ejemplo similar:

 public static void main(String[] args) { int x = 10; int y = 0; y = x + x++; //1, 2, 3, 4 x += x; //5 System.out.println("x = " + x + "; y = " + y); //6 } 

Echemos un vistazo a la operación y = x + x ++ paso a paso:

  1. Una computadora toma el valor de x y lo agrega al valor de x (10 + 10 = 20)
  2. La computadora PONE EL RESULTADO A UNA VARIABLE TEMPORAL (temp = 20)
  3. El cómputo aumenta x (10 + 1 = 11)
  4. La computadora ASIGNA EL RUPTO DE LA OPERACIÓN DEL LADO DERECHO ALMACENADA EN TEMP a variable y (20)
  5. Una computadora toma el valor de x y lo agrega al valor de x (11 + 11 = 22)
  6. El resultado final es: x = 22; y = 20

Y ahora regresemos a nuestro ejemplo y hagamos los mismos pasos:

 public static void main(String[] args) { int x = 10; x = x++; //1, 2, 3, 4 System.out.println(x); //5 } 
  1. Una computadora toma el valor de x (10)
  2. La computadora PONE EL RESULTADO EN UNA VARIABLE TEMPORAL (temp = 10)
  3. El cómputo aumenta x (10 + 1 = 11)
  4. La computadora ASIGNA EL RUPTO DE LA OPERACIÓN DEL LADO DERECHO ALMACENADO EN temperatura variable x (10)
  5. El resultado final es: x = 10

Sé que hay muchas respuestas, y una aceptada, pero aún así pondré mi granito de arena por otro punto de vista más.

Sé que esta pregunta fue C #, pero supongo que para algo como un operador de postfijo no tiene un comportamiento diferente que C:

 int main(){ int x = 0; while (x<1) x = x++; } 

El ensamblado (sí, lo edité para que sea más legible) generado por el comstackdor muestra

 ... mov -8(rbp), 0 ; x = 0 L1: cmp -8(rbp), 1 ; if x >= 1, jge L2 ; leave the loop mov eax, -8(rbp) ; t1 = x mov ecx, eax ; t2 = t1 add ecx, 1 ; t2 = t2 + 1 mov -8(rbp), ecx ; x = t2 (so x = x + 1 !) mov -8(rbp), eax ; x = t1 (kidding, it's the original value again) jmp L1 L2: ... 

De manera equivalente, el ciclo está haciendo algo como:

 t = x x = x + 1 x = t 

Nota al margen: activar cualquier optimización le da un resultado de ensamblaje como este:

 ... L1: jmp L1 ... 

¡ni siquiera se molesta en almacenar el valor que le dijo que diera x!

Como una statement independiente, x++; es tanto un incremento como una asignación. Parece que hay algunas confusiones sobre lo que sucede cuando. Si tenemos

 int x = 10; int y = (x++) + 2; 

Obtendremos x = 11 y = 12 . Se asigna el valor actual de x, y luego se produce el incremento y la reasignación de x. Entonces, cuando se usa la misma variable,

 int x = 10; // Create a variable x, and assign an initial value of 10. x = x++; // First, assign the current value of x to x. (x = x) // Second, increment x by one. (x++ - first part) // Third, assign the new value of x to x. (x++ - second part) 

De cualquier manera que lo mires, el nuevo valor de x es 11.

Estaba completamente equivocado en eso.

Explicación simple:

x ++ es un incremento postfijo.

Lo que hace el comstackdor

a) Asigne el valor de x a x b) Incremente un valor temporal de x (supongo que incluso puede optimizarse) c) Tire el valor temporal de x

Si desea que el código muestre 11 con la tarea, escriba:

x = ++ x;

El resultado de la tarea

 x = x++; 

no está definido en C y C ++ , y yo también diría lo mismo con C #.

Entonces, la secuencia real de operaciones que ocurre depende de cómo el comstackdor decida implementarla, no hay garantía de si la asignación o el incremento ocurrirá primero. (Esto está bien definido en C #, como ha señalado Jon Skeet en los comentarios. Aunque ahora siento que esta respuesta es de mucho menos valor ahora, estoy manteniendo esta publicación sin recuperar para la pregunta del OP y su respuesta en los comentarios).

Sin embargo, en este caso, parece que la secuencia de operaciones que ocurre es:

  1. se guarda el valor anterior (10) de x
  2. x se incrementa para la parte ++
  3. el valor anterior ahora está asignado a x para la asignación

De esta manera, aunque el incremento ocurre, es superado por la asignación con el valor anterior, manteniendo x en 10.

HTH