Perché questo va in un ciclo infinito?


493

Ho il codice seguente:

public class Tests {
    public static void main(String[] args) throws Exception {
        int x = 0;
        while(x<3) {
            x = x++;
            System.out.println(x);
        }
    }
}

Sappiamo che avrebbe dovuto scrivere giusto x++o x=x+1, ma su di x = x++esso dovrebbe prima attribuire xa se stesso, e successivamente incrementarlo. Perché xcontinua 0come valore?

--aggiornare

Ecco il bytecode:

public class Tests extends java.lang.Object{
public Tests();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[])   throws java.lang.Exception;
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   iconst_3
   4:   if_icmpge   22
   7:   iload_1
   8:   iinc    1, 1
   11:  istore_1
   12:  getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   15:  iload_1
   16:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
   19:  goto    2
   22:  return

}

Leggerò le istruzioni per cercare di capire ...


8
Sospetto che ciò che sta accadendo sia: 1. caricare x in un registro (= 0); 2. incremento x (x = 1); 3. salva il valore del registro in x (x = 0). In C / C ++ questo sarebbe un comportamento indefinito perché non esiste un punto di sequenza formale per definire l'ordine di 2 e 3. Speriamo che qualcuno possa citare qualcosa di equivalente dalle specifiche Java.
Rup,

19
Abbiamo provato questo in C ++ per vedere cosa sarebbe successo, e stampa 1,2,3 ed esce. Non me l'aspettavo. Presumo che sia dipendente dal compilatore, poiché si tratta di un comportamento indefinito. Abbiamo usato gnu g ++.
addolorarsi il

13
@saj x++è post-incremento; x=è assegnazione del risultato ; il risultato di x++è l'originale x(e c'è un effetto collaterale dell'incremento, ma ciò non cambia il risultato), quindi questo può essere interpretato comevar tmp = x; x++; x = tmp;
Marc Gravell

5
Ora che ho una domanda popolare di cui sono pentito, le risposte (ripetute) non smettono di arrivare, anche dopo che è stata scelta la risposta corretta. La schermata "Attività recenti" è piena delle stesse risposte, e sta arrivando di più ...
Tom Brito,

3
@Rob Vermeulen potresti voler leggere l'intera domanda prima di fare un commento ..;) Questo era un codice fatto da un mio studente, ed ero curioso del perché di questo comportamento.
Tom Brito,

Risposte:


354

Nota : in origine ho inserito il codice C # in questa risposta a scopo illustrativo, poiché C # consente di passare intparametri tramite riferimento con la refparola chiave. Ho deciso di aggiornarlo con l'effettivo codice Java legale utilizzando la prima MutableIntclasse che ho trovato su Google per una sorta di approssimazione di ciò che reffa in C #. Non posso davvero dire se questo aiuta o fa male la risposta. Dirò che personalmente non ho fatto molto sviluppo Java; quindi, per quanto ne so, potrebbero esserci modi molto più idiomatici per illustrare questo punto.


Forse se scriviamo un metodo per fare l'equivalente di ciò x++che lo renderà più chiaro.

public MutableInt postIncrement(MutableInt x) {
    int valueBeforeIncrement = x.intValue();
    x.add(1);
    return new MutableInt(valueBeforeIncrement);
}

Giusto? Incrementa il valore passato e restituisce il valore originale: questa è la definizione dell'operatore di postincremento.

Ora vediamo come si comporta questo comportamento nel tuo codice di esempio:

MutableInt x = new MutableInt();
x = postIncrement(x);

postIncrement(x)fa cosa? Incrementi x, si. E quindi restituisce ciò che x era prima dell'incremento . Questo valore restituito viene quindi assegnato a x.

Quindi l'ordine dei valori assegnati xè 0, quindi 1, quindi 0.

Questo potrebbe essere ancora più chiaro se riscriviamo quanto sopra:

MutableInt x = new MutableInt();    // x is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
x = temp;                           // Now x is 0 again.

La tua fissazione sul fatto che quando sostituisci xsul lato sinistro del compito sopra con y"puoi vedere che prima incrementa x, e successivamente lo attribuisce a y" mi sembra confuso. Non è xche viene assegnato a y; è il valore precedentemente assegnato ax . In realtà, l'iniezione yrende le cose non diverse dallo scenario sopra; abbiamo semplicemente ottenuto:

MutableInt x = new MutableInt();    // x is 0.
MutableInt y = new MutableInt();    // y is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
y = temp;                           // y is still 0.

Quindi è chiaro: x = x++effettivamente non cambia il valore di x. Fa sempre in modo che x abbia i valori x 0 , quindi x 0 + 1, quindi nuovamente x 0 .


Aggiornamento : Per inciso, per non dubitare che xvenga mai assegnato a 1 "tra" l'operazione di incremento e l'assegnazione nell'esempio sopra, ho gettato insieme una rapida demo per illustrare che questo valore intermedio effettivamente "esiste", anche se sarà mai essere "visto" sul thread in esecuzione.

La demo chiama x = x++;in loop mentre un thread separato stampa continuamente il valore di xsulla console.

public class Main {
    public static volatile int x = 0;

    public static void main(String[] args) {
        LoopingThread t = new LoopingThread();
        System.out.println("Starting background thread...");
        t.start();

        while (true) {
            x = x++;
        }
    }
}

class LoopingThread extends Thread {
    public @Override void run() {
        while (true) {
            System.out.println(Main.x);
        }
    }
}

Di seguito è riportato un estratto dell'output del programma precedente. Notare il verificarsi irregolare di entrambi 1 e 0.

Avvio del thread in background ...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1

1
Non è necessario creare una classe per passare per riferimento in Java (anche se sicuramente funzionerebbe). Puoi usare la Integerclasse, che fa parte della libreria standard, e ha anche il vantaggio di essere auto-boxata da e verso int quasi in modo trasparente.
rmeador,

3
@rmeador Integer è immutabile, quindi non è ancora possibile modificarne il valore. AtomicInteger, tuttavia, è modificabile.
ILMTitan,

5
@Dan: A proposito, xnel tuo ultimo esempio deve essere dichiarato volatile, altrimenti è un comportamento indefinito e vedere 1s è specifico dell'implementazione.
axtavt,

4
@burkestar: Non penso che il link sia abbastanza appropriato in questo caso, dato che si tratta di una domanda Java e (a meno che non mi sbagli) il comportamento in realtà non è definito in C ++.
Dan Tao,

5
@ Tom Brito - in C non è definito ... ++ potrebbe essere fatto prima o dopo l'assegnazione. In pratica, potrebbe esserci un compilatore che fa la stessa cosa di Java, ma non ci si vorrebbe scommettere.
detly

170

x = x++ funziona nel modo seguente:

  • Innanzitutto valuta l'espressione x++. La valutazione di questa espressione produce un valore di espressione (che è il valore xprima dell'incremento) e incrementi x.
  • Successivamente assegna il valore dell'espressione a x, sovrascrivendo il valore incrementato.

Quindi, la sequenza di eventi appare come segue (è un bytecode decompilato, come prodotto da javap -c, con i miei commenti):

   8: iload_1 // Ricorda il valore corrente di x nello stack
   9: iinc 1, 1 // Incrementa x (non cambia lo stack)
   12: istore_1 // Scrivi il valore ricordato dallo stack in x

Per confronto, x = ++x:

   8: iinc 1, 1 // Incremento x
   11: iload_1 // Inserisce il valore di x nello stack
   12: istore_1 // Pop valore dallo stack a x

se fai un test, puoi vedere che prima aumenta e poi attributi. Quindi non dovrebbe attribuire zero.
Tom Brito,

2
@Tom è questo il punto, però - poiché questa è tutta una singola sequenza che sta facendo le cose in un ordine non ovvio (e probabilmente non definito). Tentando di verificarlo si aggiunge un punto sequenza e si ottiene un comportamento diverso.
Rup,

Per quanto riguarda l'output del bytecode: nota che iincincrementa una variabile, non aumenta un valore di stack, né lascia un valore sullo stack (diversamente da quasi ogni altra operazione aritmetica). Potresti voler aggiungere il codice generato da ++xper il confronto.
Anon,

3
@Rep Potrebbe non essere definito in C o C ++, ma in Java, è ben definito.
ILMTitan,


104

Ciò accade perché il valore di xnon viene affatto incrementato.

x = x++;

è equivalente a

int temp = x;
x++;
x = temp;

Spiegazione:

Diamo un'occhiata al codice byte per questa operazione. Prendi in considerazione una classe di esempio:

class test {
    public static void main(String[] args) {
        int i=0;
        i=i++;
    }
}

Ora eseguendo il disassemblatore di classe su questo otteniamo:

$ javap -c test
Compiled from "test.java"
class test extends java.lang.Object{
test();
  Code:
   0:    aload_0
   1:    invokespecial    #1; //Method java/lang/Object."<init>":()V
   4:    return

public static void main(java.lang.String[]);
  Code:
   0:    iconst_0
   1:    istore_1
   2:    iload_1
   3:    iinc    1, 1
   6:    istore_1
   7:    return
}

Ora la VM Java è basata sullo stack, il che significa che per ogni operazione, i dati verranno inseriti nello stack e dallo stack, i dati verranno espulsi per eseguire l'operazione. Esiste anche un'altra struttura di dati, in genere un array per memorizzare le variabili locali. Alle variabili locali vengono dati ID che sono solo gli indici dell'array.

Vediamo i mnemonici in main()metodo:

  • iconst_0: Il valore costante 0 viene inserito nello stack.
  • istore_1: L'elemento superiore dello stack viene estratto e memorizzato nella variabile locale con l'indice 1
    che è x.
  • iload_1: Il valore nella posizione 1che è il valore di x cui è 0, viene spinto nella pila.
  • iinc 1, 1: Il valore nella posizione di memoria 1viene incrementato di 1. Così xora diventa 1.
  • istore_1: Il valore nella parte superiore dello stack viene archiviato nella posizione di memoria 1. Questo è 0assegnato alla x sovrascrittura del suo valore incrementato.

Quindi il valore di xnon cambia, risultando nel ciclo infinito.


5
In realtà viene incrementato (questo è il significato di ++), ma la variabile viene sovrascritta in seguito.
Progman,

10
int temp = x; x = x + 1; x = temp;è meglio non usare una tautologia nel tuo esempio.
Scott Chamberlain,

52
  1. La notazione con prefisso aumenterà la variabile PRIMA che l'espressione venga valutata.
  2. La notazione Postfix aumenterà DOPO la valutazione dell'espressione.

Tuttavia " =" ha una precedenza di operatore inferiore a "++ ".

Quindi x=x++;dovrebbe valutare come segue

  1. x preparato per l'incarico (valutato)
  2. x incrementato
  3. Valore precedente di xassegnato a x.

Questa è la risposta migliore Alcuni markup lo avrebbero aiutato a distinguersi un po 'di più.
Justin Force,

1
Questo è sbagliato. Non si tratta di precedenza. ++ha una precedenza maggiore rispetto =a C e C ++, ma l'istruzione non è definita in tali lingue.
Matthew Flaschen,

2
La domanda originale riguarda Java
Jaydee,

34

Nessuna delle risposte è abbastanza precisa, quindi ecco qui:

Quando stai scrivendo int x = x++, non stai assegnando xdi essere se stesso con il nuovo valore, stai assegnando xcome valore di ritorno x++dell'espressione. Che sembra essere il valore originale dix , come suggerito nella risposta di Colin Cochrane .

Per divertimento, prova il seguente codice:

public class Autoincrement {
        public static void main(String[] args) {
                int x = 0;
                System.out.println(x++);
                System.out.println(x);
        }
}

Il risultato sarà

0
1

Il valore restituito dell'espressione è il valore iniziale di x, che è zero. Ma più tardi, quando leggiamo il valore di x, riceviamo il valore aggiornato, ovvero uno.


Cercherò di capire le linee del bytecode, vedrò il mio aggiornamento, quindi sarà chiaro .. :)
Tom Brito,

L'uso di println () mi è stato di grande aiuto nel capire questo.
ErikE,

29

È già stato spiegato bene da altri. Includo solo i collegamenti alle sezioni relative alle specifiche Java.

x = x ++ è un'espressione. Java seguirà l' ordine di valutazione . Per prima cosa valuterà l'espressione x ++, che incrementerà x e imposterà il valore del risultato sul valore precedente di x . Quindi assegnerà il risultato dell'espressione alla variabile x. Alla fine, x è tornato al suo valore precedente.


1
+1. Questa è di gran lunga la migliore risposta alla domanda reale, "Perché?"
Matthew Flaschen,

18

Questa dichiarazione:

x = x++;

valuta in questo modo:

  1. Spingere x sulla pila;
  2. Incremento x ;
  3. Pop xdalla pila.

Quindi il valore è invariato. Confrontalo con:

x = ++x;

che valuta come:

  1. Incrementox ;
  2. Spingerex sulla pila;
  3. Pop xdalla pila.

Quello che vuoi è:

while (x < 3) {
  x++;
  System.out.println(x);
}

13
Sicuramente l'implementazione corretta, ma la domanda è "perché?".
p

1
Il codice originale utilizzava post-incremento su x e quindi lo assegnava a x. x verrà associato a x prima dell'incremento, pertanto non cambierà mai i valori.
wkl,

5
@cletus Non sono il downvoter, ma la tua risposta iniziale non conteneva la spiegazione. Ha appena detto di fare 'x ++ `.
Petar Minchev,

4
@cletus: non ho effettuato il downgrade, ma la tua risposta originariamente era solo lo x++snippet di codice.
p

10
Anche la spiegazione è errata. Se il codice prima assegnasse da x a x e poi incrementasse x, funzionerebbe benissimo. Cambia semplicemente la x++;tua soluzione x=x; x++;e stai facendo ciò che affermi che stia facendo il codice originale.
Wooble,

10

La risposta è piuttosto semplice. Ha a che fare con l'ordine in cui le cose vengono valutate. x++restituisce il valorex quindi aumentax .

Di conseguenza, il valore dell'espressione x++è 0. Quindi stai assegnando x=0ogni volta nel ciclo. x++Incrementa sicuramente questo valore, ma ciò accade prima dell'assegnazione.


1
Wow, ci sono così tanti dettagli in questa pagina quando la risposta è breve e semplice, cioè questa.
Charles Goodwin,

8

Da http://download.oracle.com/javase/tutorial/java/nutsandbolts/op1.html

Gli operatori di incremento / decremento possono essere applicati prima (prefisso) o dopo (postfisso) l'operando. Il risultato del codice ++; e ++ risultato; terminerà entrambi con un incremento di uno. L'unica differenza è che la versione del prefisso (risultato ++) restituisce il valore incrementato, mentre la versione postfisso (risultato ++) restituisce il valore originale . Se stai semplicemente eseguendo un semplice incremento / decremento, non importa davvero quale versione scegli. Ma se si utilizza questo operatore in parte con un'espressione più ampia, quella scelta può fare una differenza significativa.

Per illustrare, prova quanto segue:

    int x = 0;
    int y = 0;
    y = x++;
    System.out.println(x);
    System.out.println(y);

Che stamperà 1 e 0.


1
Non è il risultato della valutazione il problema, tuttavia, è l'ordine dei negozi.
Rup,

2
Non sono d'accordo. Se x = 0 allora x ++ restituirà 0. Pertanto x = x ++ si tradurrà in x = 0.
Colin Cochrane,

Rup ha ragione su questo. In questo caso particolare è l'ordine dei negozi. y = x ++ non è uguale a x = x ++; Su quest'ultimo, a x vengono assegnati 2 valori nella stessa espressione. Alla mano sinistra x viene assegnato il risultato della valutazione dell'espressione x ++, che è 0. Il lato destro x viene incrementato a 1. In quale ordine si verificano questi 2 incarichi è il problema. Dai post precedenti è chiaro che il modo in cui funziona è: eval = x ++ => eval == 0: incremento a destra x => x == 1: sinistra x = eval => x == 0
Michael Ekoka

7

Stai effettivamente ottenendo il seguente comportamento.

  1. prendi il valore di x (che è 0) come "il risultato" del lato destro
  2. incrementa il valore di x (quindi x ora è 1)
  3. assegnare il risultato del lato destro (che è stato salvato come 0) a x (x ora è 0)

L'idea è che l'operatore post-incremento (x ++) incrementa quella variabile in questione DOPO restituire il suo valore per l'uso nell'equazione in cui è usato.

Modifica: aggiungere un po 'a causa del commento. Consideralo come il seguente.

x = 1;        // x == 1
x = x++ * 5;
              // First, the right hand side of the equation is evaluated.
  ==>  x = 1 * 5;    
              // x == 2 at this point, as it "gave" the equation its value of 1
              // and then gets incremented by 1 to 2.
  ==>  x = 5;
              // And then that RightHandSide value is assigned to 
              // the LeftHandSide variable, leaving x with the value of 5.

OK, ma cosa specifica l'ordine dei passaggi 2 e 3?
Rup,

@Rup: la lingua lo definisce. Il lato destro dell'equazione viene valutato per primo (in questo caso, "x ++") e il risultato viene assegnato alla variabile sul lato sinistro. Ecco come funziona la lingua. Per quanto riguarda "x ++" "restituendo" x per l'equazione, è così che funziona l'operatore di incremento postfix (restituisce il valore di x, quindi incrementalo). Se fosse stato "--x", lo sarebbe stato (incrementare x, quindi restituire il valore). Return non è la parola giusta lì, ma hai l'idea.
RHSeeger,

7

Non hai davvero bisogno del codice macchina per capire cosa sta succedendo.

Secondo le definizioni:

  1. L'operatore di assegnazione valuta l'espressione sul lato destro e la memorizza in una variabile temporanea.

    1.1. Il valore corrente di x viene copiato in questa variabile temporanea

    1.2. x è ora incrementato.

  2. La variabile temporanea viene quindi copiata nella parte sinistra dell'espressione, che è x per caso! Ecco perché il vecchio valore di x viene nuovamente copiato in se stesso.

È abbastanza semplice


5

Questo perché non viene mai incrementato in questo caso. x++utilizzerà il valore di esso prima di incrementare come in questo caso sarà come:

x = 0;

Ma se lo fai ++x;aumenterà.


se fai un test, puoi vedere che prima aumenta e poi attributi. Quindi non dovrebbe attribuire zero.
Tom Brito,

1
@ Tom: vedi la mia risposta - Dimostro in un test che x ++ in realtà restituisce il vecchio valore di x. Ecco dove si rompe.
Robert Munteanu,

"se fai un test" - alcune persone sembrano pensare che un test scritto in C ci dica cosa farà Java, quando non ci dirà nemmeno cosa farà C.
Jim Balter,

3

Il valore rimane a 0 perché il valore di x++è 0. In questo caso non importa se il valore di xviene aumentato o meno, l'assegnazione x=0viene eseguita. Questo sovrascriverà il valore incrementato temporaneo di x(che era 1 per un "tempo molto breve").


Ma x ++ è un'operazione post. Quindi x dovrebbe essere incrementato dopo che l'assegnazione è stata completata.
Sagar V,

1
@Sagar V: solo per l'espressione x++, non per l'intero incaricox=x++;
Progman

No, penso che debba essere incrementato solo dopo aver letto il valore di x da utilizzare nell'assegnazione.
Rup,

1

Questo funziona come ti aspetti dall'altro. È la differenza tra prefisso e postfisso.

int x = 0; 
while (x < 3)    x = (++x);

1

Pensa a x ++ come a una chiamata di funzione che "restituisce" ciò che X era prima dell'incremento (ecco perché si chiama post-incremento).

Quindi l'ordine delle operazioni è:
1: memorizza nella cache il valore di x prima di incrementare
2: incrementa x
3: restituisce il valore memorizzato nella cache (x prima che fosse incrementato)
4: il valore restituito è assegnato a x


OK, ma cosa specifica l'ordine dei passaggi 3 e 4?
Rup,

"restituisce ciò che X era prima dell'incremento" è sbagliato, vedi il mio aggiornamento
Tom Brito,

In realtà i passaggi 3 e 4 non sono operazioni separate: in realtà non è una chiamata di funzione che restituisce un valore, aiuta solo a pensarlo in quel modo. Ogni volta che hai un compito, il lato destro viene "valutato", quindi il risultato viene assegnato al lato sinistro, il risultato della valutazione può essere considerato come un valore di ritorno in quanto ti aiuta a capire l'ordine delle operazioni, ma non è proprio .
Jhabbott,

Oops, vero. Intendevo i passaggi 2 e 4: perché il valore restituito viene archiviato sopra il valore incrementato?
Rup,

1
Questo fa parte della definizione di un'operazione di assegnazione, prima viene valutato completamente il lato destro, quindi il risultato viene assegnato al lato sinistro.
Jhabbott,

1

Quando ++ è su rhs, il risultato viene restituito prima che il numero venga incrementato. Passa a ++ x e sarebbe andato tutto bene. Java avrebbe ottimizzato questo per eseguire una singola operazione (l'assegnazione di xx) piuttosto che l'incremento.


1

Per quanto posso vedere, l'errore si verifica, a causa dell'assegnazione che ha la precedenza sul valore incrementato, con il valore prima dell'incremento, ovvero annulla l'incremento.

In particolare, l'espressione "x ++" ha il valore di "x" prima dell'incremento rispetto a "++ x" che ha il valore di "x" dopo l'incremento.

Se sei interessato a studiare il bytecode, daremo uno sguardo alle tre righe in questione:

 7:   iload_1
 8:   iinc    1, 1
11:  istore_1

7: iload_1 # Metterà il valore della seconda variabile locale nello stack
8: iinc 1,1 # aumenterà la seconda variabile locale di 1, nota che lascia lo stack intatto!
9: istore_1 # farà apparire la parte superiore dello stack e salverà il valore di questo elemento nella seconda variabile locale
(puoi leggere gli effetti di ciascuna istruzione JVM qui )

Questo è il motivo per cui il codice sopra riportato verrà eseguito in modo indefinito, mentre la versione con ++ x non lo farà. Il bytecode per ++ x dovrebbe apparire alquanto diverso, per quanto mi ricordo dal compilatore Java 1.3 che ho scritto poco più di un anno fa, il bytecode dovrebbe andare in questo modo:

iinc 1,1
iload_1
istore_1

Quindi, scambiando le prime due righe, cambia la semantica in modo che il valore lasciato in cima allo stack, dopo l'incremento (ovvero il "valore" dell'espressione) sia il valore dopo l'incremento.


1
    x++
=: (x = x + 1) - 1

Così:

   x = x++;
=> x = ((x = x + 1) - 1)
=> x = ((x + 1) - 1)
=> x = x; // Doesn't modify x!

Mentre

   ++x
=: x = x + 1

Così:

   x = ++x;
=> x = (x = x + 1)
=> x = x + 1; // Increments x

Naturalmente il risultato finale è lo stesso di solo x++;o ++x;su una linea da solo.


0
 x = x++; (increment is overriden by = )

a causa dell'istruzione precedente x non raggiunge mai 3;


0

Mi chiedo se c'è qualcosa nelle specifiche Java che definisce esattamente il comportamento di questo. (La conseguenza evidente di questa affermazione è che sono troppo pigro per controllare.)

Nota dal bytecode di Tom, le linee chiave sono 7, 8 e 11. La linea 7 carica x nello stack di calcolo. Linea 8 incrementi x. La riga 11 memorizza il valore dallo stack alla x. In casi normali in cui non si stanno riassegnando valori a se stessi, non penso che ci sarebbe alcun motivo per cui non è possibile caricare, archiviare, quindi incrementare. Otterresti lo stesso risultato.

Supponiamo che tu abbia avuto un caso più normale in cui hai scritto qualcosa del tipo: z = (x ++) + (y ++);

Se lo dicesse (pseudocodice per saltare i tecnicismi)

load x
increment x
add y
increment y
store x+y to z

o

load x
add y
store x+y to z
increment x
increment y

dovrebbe essere irrilevante. O l'implementazione dovrebbe essere valida, penso.

Sarei estremamente cauto nello scrivere codice che dipende da questo comportamento. Mi sembra molto dipendente dall'implementazione, tra le "crepe" nelle specifiche. L'unica volta che farebbe la differenza è se hai fatto qualcosa di folle, come nell'esempio qui, o se avessi due thread in esecuzione e dipendessi dall'ordine di valutazione all'interno dell'espressione.



0

L' x++espressione valuta x. La ++parte influisce sul valore dopo la valutazione , non dopo la dichiarazione . così x = x++viene efficacemente tradotto in

int y = x; // evaluation
x = x + 1; // increment part
x = y; // assignment

0

Prima di incrementare il valore di uno, il valore viene assegnato alla variabile.


0

Sta accadendo perché è post incrementato. Significa che la variabile viene incrementata dopo la valutazione dell'espressione.

int x = 9;
int y = x++;

x ora è 10, ma y è 9, il valore di x prima che fosse incrementato.

Vedi di più in Definizione dell'incremento postale .


1
Il tuo x/ yesempio è diverso dal codice reale e la differenza è rilevante. Il tuo link non menziona nemmeno Java. Per due delle lingue che fa parlare, la dichiarazione in questione non è definito.
Matthew Flaschen,

0

Controlla il codice qui sotto,

    int x=0;
    int temp=x++;
    System.out.println("temp = "+temp);
    x = temp;
    System.out.println("x = "+x);

l'output sarà,

temp = 0
x = 0

post incrementsignifica incrementare il valore e restituire il valore prima dell'incremento . Ecco perché il valore tempè 0. Quindi cosa succede se temp = ie questo è in un ciclo (ad eccezione della prima riga di codice). proprio come nella domanda !!!!


-1

L'operatore di incremento viene applicato alla stessa variabile a cui si sta assegnando. Chiede problemi. Sono sicuro che puoi vedere il valore della tua variabile x mentre esegui questo programma .... questo dovrebbe chiarire perché il ciclo non finisce mai.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.