¿Qué es x después de “x = x ++”?

¿Qué sucede (detrás de las cortinas) cuando se ejecuta esto?

int x = 7; x = x++; 

Es decir, ¿cuándo una variable se incrementa y se asigna a sí misma en una statement? Compilé y ejecuté esto. x sigue siendo 7 incluso después de la statement completa . ¡En mi libro, dice que x se incrementa!

x se incrementa Pero estás asignando el antiguo valor de x a sí mismo.

 x = x++; 

x++ incrementa x y devuelve su valor anterior. x = asigna el valor anterior a sí mismo.

Entonces, al final, x se vuelve a asignar a su valor inicial.

 x = x++; 

es equivalente a

 int tmp = x; x++; x = tmp; 

La statement:

 x = x++; 

es equivalente a:

 tmp = x; // ... this is capturing the value of "x++" x = x + 1; // ... this is the effect of the increment operation in "x++" which // happens after the value is captured. x = tmp; // ... this is the effect of assignment operation which is // (unfortunately) clobbering the incremented value. 

En resumen, la statement no tiene ningún efecto.

Los puntos clave:

  • El valor de una expresión de incremento / decremento Postfix es el valor del operando antes de que tenga lugar el incremento / decremento. (En el caso de un formulario Prefijo, el valor es el valor del operando después de la operación,)

  • el RHS de una expresión de asignación se evalúa por completo (incluidos los incrementos, decrementos y / u otros efectos secundarios) antes de que el valor se asigne al LHS.

Tenga en cuenta que, a diferencia de C y C ++, el orden de evaluación de una expresión en Java está totalmente especificado y no hay espacio para la variación específica de la plataforma. Los comstackdores solo pueden reordenar las operaciones si esto no cambia el resultado de ejecutar el código desde la perspectiva del hilo actual. En este caso, se le permitiría a un comstackdor optimizar la statement completa porque se puede probar que no es operativa.


En caso de que no sea ya obvio:

  • “x = x ++;” es casi seguro un error en cualquier progtwig.
  • ¡El OP (para la pregunta original!) Probablemente significó “x ++;” en lugar de “x = x ++;”.
  • Las declaraciones que combinan autoinc / decrement y asignación en la misma variable son difíciles de entender, y por lo tanto deben evitarse independientemente de su corrección . Simplemente no hay necesidad de escribir un código como ese.

Con suerte, las comprobaciones de código como FindBugs y PMD marcarán código como este como sospechoso.

 int x = 7; x = x++; 

Tiene un comportamiento indefinido en C y para Java ver esta respuesta . Depende del comstackdor lo que sucede.

Una construcción como x = x++; indica que probablemente estés entendiendo mal lo que hace el operador ++ :

 // original code int x = 7; x = x++; 

Vamos a reescribir esto para hacer lo mismo, basado en eliminar el operador ++ :

 // behaves the same as the original code int x = 7; int tmp = x; // value of tmp here is 7 x = x + 1; // x temporarily equals 8 (this is the evaluation of ++) x = tmp; // oops! we overwrote y with 7 

Ahora, vamos a reescribirlo para hacer (lo que yo pienso) que querías:

 // original code int x = 7; x++; 

La sutileza aquí es que el operador ++ modifica la variable x , a diferencia de una expresión como x + x , que evaluaría a un valor int pero dejaría la variable x misma sin cambios. Considere un constructo como el venerable bucle:

 for(int i = 0; i < 10; i++) { System.out.println(i); } 

Observe el i++ allí? Es el mismo operador. Podríamos reescribir esto for bucle como este y se comportaría de la misma manera:

 for(int i = 0; i < 10; i = i + 1) { System.out.println(i); } 

También recomiendo no usar el operador ++ en expresiones más grandes en la mayoría de los casos. Debido a la sutileza de cuando modifica la variable original en pre y post incremento ( ++x y x++ , respectivamente), es muy fácil introducir errores sutiles que son difíciles de rastrear.

Según el código de Byte obtenido de los archivos de clase,

Ambas asignaciones incrementan x, pero la diferencia es el momento when the value is pushed onto the stack

En el Case1 , se produce el Case1 (y luego se le asigna) antes del incremento (lo que esencialmente significa que su incremento no hace nada)

En el Case2 , el incremento ocurre primero (lo que lo convierte en 8) y luego se empuja hacia la stack (y luego se asigna a x)

Caso 1:

 int x=7; x=x++; 

Código de Byte:

 0 bipush 7 //Push 7 onto stack 2 istore_1 [x] //Pop 7 and store in x 3 iload_1 [x] //Push 7 onto stack 4 iinc 1 1 [x] //Increment x by 1 (x=8) 7 istore_1 [x] //Pop 7 and store in x 8 return //x now has 7 

Caso 2

 int x=7; x=++x; 

Código de Byte

 0 bipush 7 //Push 7 onto stack 2 istore_1 [x] //Pop 7 and store in x 3 iinc 1 1 [x] //Increment x by 1 (x=8) 6 iload_1 [x] //Push x onto stack 7 istore_1 [x] //Pop 8 and store in x 8 return //x now has 8 
  • Astackr aquí se refiere a la stack de operandos, local: índice x: 1 tipo: int

Se incrementa después de ” x = x++; “. Sería 8 si lo hiciera ” x = ++x; “.

El incremento ocurre después de que se llama a x, por lo que x todavía es igual a 7. ++ x sería igual a 8 cuando se llama x

Cuando reasignas el valor de x , sigue siendo 7. Intenta x = ++x y obtendrás 8 else do

 x++; // don't re-assign, just increment System.out.println(x); // prints 8 

porque x ++ incrementa el valor DESPUÉS de asignarlo a la variable. así sucesivamente y durante la ejecución de esta línea:

 x++; 

el varialbe x seguirá teniendo el valor original (7), pero usando x nuevamente en otra línea, como

 System.out.println(x + ""); 

te dará 8.

Si desea usar un valor incrementado de x en su statement de asignación, use

 ++x; 

Esto incrementará x en 1, luego asigna ese valor a la variable x.

[Editar] en lugar de x = x ++, es solo x ++; el primero asigna el valor original de x a sí mismo, por lo que en realidad no hace nada en esa línea.

El operador Post Increment funciona de la siguiente manera:

  1. Almacenar el valor anterior del operando.
  2. Incrementa el valor del operando.
  3. Devuelve el valor anterior del operando.

Entonces la statement

 int x = 7; x = x++; 

se evaluaría de la siguiente manera:

  1. x se inicializa con el valor 7
  2. el operador de incremento posterior almacena el valor anterior de x, es decir, 7 para regresar.
  3. Incrementa la x, entonces ahora x es 8
  4. Devuelve el valor anterior de x, es decir, 7 y se vuelve a asignar a x, por lo que x vuelve a ser 7

Entonces, x aumenta de hecho, pero dado que x ++ está asignando el resultado a x, el valor de x se anula a su valor anterior.

¿Qué sucede cuando int x = 7; x = x++; int x = 7; x = x++; ?

ans -> x++ significa primer valor de uso de x para la expresión y luego boostlo en 1.
Esto es lo que sucede en tu caso. El valor de x en RHS se copia a la variable x en LHS y luego el valor de x aumenta en 1.

De forma similar ++x significa -> boost el valor de x primero por uno y luego usar en expresión.
Entonces en tu caso si haces x = ++x ; // where x = 7 x = ++x ; // where x = 7
obtendrás un valor de 8.

Para mayor claridad intente averiguar cuántas instrucciones printf ejecutarán el siguiente código

 while(i++ <5) printf("%d" , ++i); // This might clear your concept upto great extend 

++x es preincremento -> x se incrementa antes de ser utilizado
x++ es un incremento posterior -> x se incrementa después de ser utilizado

 int x = 7; -> x get 7 value 
x = x++; -> x get x value AND only then x is incremented

Entonces esto significa: x++ no es igual a x = x+1

porque:

 int x = 7; x = x++; x is 7 int x = 7; x = x = x+1; x is 8 

y ahora parece un poco extraño:

 int x = 7; x = x+=1; x is 8 

muy dependiente del comstackdor

Creo que esta controversia se puede resolver sin entrar en el código y solo pensar.

Considere i ++ & ++ i como funciones, digamos Func1 y Func2.

Ahora i = 7;
Func1 (i ++) devuelve 7, Func2 (++ i) devuelve 8 (todo el mundo lo sabe). Internamente, ambas funciones aumentan de i a 8, pero devuelven valores diferentes.

Entonces i = i ++ llama a la función Func1. Dentro de la función, aumenta a 8, pero al finalizar, la función devuelve 7.

Entonces finalmente 7 se asigna a i. (Entonces, al final, i = 7)

x = x ++;

Este es el operador de incremento posterior. Debe entenderse como “Usar el valor del operando y luego incrementar el operando”.

Si desea que ocurra lo contrario, es decir, “Incremente el operando y luego use el valor del operando”, debe usar el operador de preincremento como se muestra a continuación.

x = ++ x;

Este operador primero incrementa el valor de x en 1 y luego asigna el valor a x.

Esto se debe a que utilizó un operador de incremento posterior. En esta siguiente línea de código

 x = x++; 

Lo que ocurre es que estás asignando el valor de x a x. x ++ aumenta x luego de que el valor de x se asigna a x. Así es como funcionan los operadores de post-incremento. Funcionan después de que se ha ejecutado una statement. Entonces, en su código, x es devuelto primero luego de que luego se incrementa.

Si lo hiciste

 x = ++x; 

La respuesta sería 8 porque usaste el operador de preincremento. Esto incrementa el valor primero antes de devolver el valor de x.