2008-10-22 20 views
51

¿Alguna vez ha intentado esto antes?¿Cuál es la diferencia entre X = X ++; vs X ++ ;?

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

de salida: 10.

pero para

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

de salida: 11.

Podría alguien explicar por qué esto?

+16

Wow - No creo que haya visto tantas respuestas incorrectas aquí ... –

+3

Y la moraleja de la historia es evitar escribir eso en el código de producción :) –

+0

Estoy totalmente de acuerdo contigo, Debería evitar escribir estos fragmentos de código en el código de producción como Jon dijo, muchas respuestas incorrectas, esto puede causar muchos problemas durante cualquier proyecto. – Ahmed

Respuesta

69

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

Así que en este caso:

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

Tiene X a las 11 sólo por un momento, luego se pone de nuevo a 10 porque el 10 es el valor de retorno de (x ++).

Se podría en lugar de 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 usted tendría su resultado esperado de 11 si se hubiera hecho:

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

x = ++ x parece bastante inútil, no veo particularmente una razón para ninguno de esos constructos ... solo x ++ o ++ x .. o qué tal x = x + ((Techo (Abs (x)) + 1))/(Techo (Abs (x) + 1))) que debería funcionar también – stephenbayer

+4

de acuerdo, pero creo que la pregunta era solo preguntar por qué reacciona así. –

+4

La primera frase es incorrecta, x ++ primero devolverá el valor y luego incrementará - mientras que ++ x primero incrementará, luego devolverá el valor. –

57

En el asignación x = x++ usted primer extraiga 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, asigne los resultados de la evaluación de expresión (10) al x a través de la declaración de asignación.

Tal vez un código equivalente haría que la situación clara:

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

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

+0

Eso me suena extraño ... mi impresión es que el cambio debería haberse aplicado antes de que x acceda a Console.Writeline –

+0

El problema es la diferencia entre pre-fix y -post-fix. x ++ y ++ x se comportan de manera diferente. – jjnguy

+0

El cambio se aplicó pero se perdió en la tarea. Si usas y = x ++ en su lugar o si lo haces x = ++ x; el primer ejemplo también dará salida a 11. –

14

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

So x = x ++; simplemente poner será

1. retorno el valor, entonces

2. Valor mínimo de x, entonces

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

11

x = x ++

sería igual a 11.

4

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

x = x++; 

?

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

+0

Puede ser, nadie puede utilizar x = x ++, pero que se puede encontrar este static void main (String [] args) { int x = 10; int y = x ++; Console.WriteLine (y); } Salida: 10. Entonces, ¿por qué? – Ahmed

7
x++; 

realiza lo siguiente:

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

Como se puede ver, se guarda el valor original, se incrementa x, 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 (asumiendo sin optimización del compilador).

-4

El resultado de la asignación

x = x++; 

no está definido en C y C++ , y me imagino lo mismo con C# también.

Entonces, la secuencia real de operaciones que se produce depende de cómo el compilador 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 sucede es:

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

De este modo, aunque se produce el incremento, que es superada por la asignación con valor antiguo, manteniendo así en x 10.

HTH

+0

Está muy bien definido en C#, que generalmente es un lenguaje más sano que C o C++ cuando se trata de este tipo de cosas. –

+0

3. el valor anterior ahora está asignado a x para la asignación ¿Por qué el valor anterior, no el valor después de que se incrementa? – Ahmed

+0

Porque el valor de una expresión de incremento posterior es el resultado antes de que se incrementara. –

-2

Como una declaración independiente, x++; es tanto un incremento y 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 y = 12. Se asigna el valor actual de x, y luego se lleva a cabo el incremento y la reasignación de x. Por lo tanto, cuando se utiliza 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 forma que se mire, el nuevo valor de x es 11.

yo estaba completamente equivocado en eso.

+0

No, la secuencia correcta es "determinar el valor actual de xy recordarlo; incrementar x; asignar el valor recordado a x" - de ahí que el valor final de x sea 10. –

+0

El valor final es 10. – Ahmed

+3

Wow. Es 10. Estoy editando mi propia basura. –

0

Pruebe llamar a ++ x y vea si eso funciona.

3

usted puede pensar en ello como esto:

int x = 10; 

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

x = x++; 

Esto se puede analizar a:

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.

0

poniendo el operador de incremento después de la variable significa que el incremento y la asignación ocurre después se evalúa la expresión ... así La declaración original x = x ++ ; se traduce en x 1. Evaluar y almacenar el valor en la memoria tyransient ... Ahora ejecutar código solicitado por el operador ++ .... (pasos 2 & 3) 2. Incrementar el valor de x (en la memoria transitoria) 3. Asignar valor incrementado a la ubicación de almacenamiento de x ... Ahora, continúe con el resto 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 del signo = ... que es x

-3

explicación simple:

x ++ es una incrementación de sufijo.

Lo que hace el compilador:

a) Asignar el valor de x para x b) Aumentar un valor temporal de x (supongo que puede ser incluso optimizado de distancia) c) El tiro valor de distancia temporal de x

Si desea que el código de retorno 11 con la asignación, escribir:

x = x ++;

+1

¿Por qué responde usted a una pregunta de dos años que ya tiene una respuesta correcta? No es suficiente que brinde la misma respuesta que ya se dio. – Oliver

+3

¡Porque puedo! :-RE – stormianrootsolver

1

El primero que se hace es llamado "post-incremento" lo que significa que

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

por lo que el momento en que se asignan 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 del enunciado, lo que significa que se incrementará después de; ?

0

Tal vez no estoy en lo cierto, pero es más fácil de entender para mí 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 
} 

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

  1. Un ordenador toma el valor de x y añadirlo a valor de x (10 + 10 = 20)
  2. el ordenador pone el resultado a una variable temporal (temp = 20)
  3. los incrementos coputer x (1 0 + 1 = 11)
  4. La computadora ASIGNA EL RUSLO DE LA OPERACIÓN DEL LADO DERECHO ALMACENADO EN temperatura a variable y (20)
  5. Una computadora toma el valor de xy lo agrega al valor de x (11 + 11 = 22)
  6. El resultado final es: x = 22; y = 20

Y ahora volvamos a la de nuestro ejemplo y hacer 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. El equipo pone el RESULTADO A 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 temp a variab Le x (10)
  5. El resultado final es: x = 10
0

Sé que hay un montón de respuestas, y un acepté, pero todavía me pongo mi granito de arena para otro punto de vista.

Sé que esta pregunta fue de C#, pero supongo que por algo así como un operador de sufijo no tiene un comportamiento diferente de C:

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

El conjunto (sí, he editado para que sea más legible) generado por el compilador 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 bucle está haciendo algo como:

t = x 
x = x + 1 
x = t 

Nota al margen: encender ninguna optimizaciones que da un resultado de montaje como éste:

... 
L1: 
    jmp L1 
... 

que ni siquiera se molesta para almacenar el valor que le dijo que para dar x!

Cuestiones relacionadas