Per i = 0, perché (i + = i ++) è uguale a 0?


253

Prendi il seguente codice (utilizzabile come applicazione console):

static void Main(string[] args)
{
    int i = 0;
    i += i++;
    Console.WriteLine(i);
    Console.ReadLine();
}

Il risultato iè 0. Mi aspettavo 2 (come hanno fatto alcuni miei colleghi). Probabilmente il compilatore crea una sorta di struttura che risulta iessere zero.

Il motivo per cui mi aspettavo 2 è che, nella mia linea di pensiero, l'istruzione della mano destra verrebbe valutata per prima, incrementando i di 1. Di quanto non venga aggiunto a i. Dato che io sono già 1, sta aggiungendo 1 a 1. Quindi 1 + 1 = 2. Ovviamente non è quello che sta succedendo.

Puoi spiegare cosa fa il compilatore o cosa succede in fase di esecuzione? Perché il risultato è zero?

Disclaimer: sono assolutamente consapevole che non utilizzerai (e probabilmente non dovresti) questo codice. So che non lo farò mai. Tuttavia, trovo interessante sapere perché agisce in questo modo e cosa sta succedendo esattamente.


57
il risultato atteso non dovrebbe essere 1? i (0) + = i ++ (1) quindi 0 + = 1 = 1
alleazione

11
Funziona come previsto
Steve è il

177
Quante varianti di questa domanda verranno poste?
mowwwalker,

20
La preincrementazione aumenterà il valore prima di fare l'iscrizione i + = ++ ti darò 1
Pierluc SS

21
Perché tutti si stanno concentrando sul pre-postincremento? La cosa "strana" è che il valore di isul lato sinistro di +=è "memorizzato nella cache" prima che il lato destro venga valutato. Ciò è controintuitivo, poiché, ad esempio, richiederebbe un'operazione di copia se ifosse un oggetto. (Per favore, non capirmi male: sono assolutamente d'accordo nel dichiarare che questa 0è la risposta corretta e conforme agli standard.)
JohnB

Risposte:


425

Questo:

int i = 0;
i += i++

Può essere visto come stai (la seguente è una semplificazione eccessiva):

int i = 0;
i = i + i; // i=0 because the ++ is a postfix operator and hasn't been executed
i + 1; // Note that you are discarding the calculation result

Ciò che realmente accade è più coinvolto di così: dai un'occhiata agli operatori di incremento e decremento di Postfix 7.5.9 :

L'elaborazione runtime di un'operazione di incremento o decremento postfix del modulo x ++ o x-- comprende i seguenti passaggi:

  • Se x è classificato come variabile:

    • x viene valutato per produrre la variabile.
    • Il valore di x viene salvato.
    • L'operatore selezionato viene invocato con il valore salvato di x come argomento.
    • Il valore restituito dall'operatore viene memorizzato nella posizione indicata dalla valutazione di x.
    • Il valore salvato di x diventa il risultato dell'operazione.

Si noti che a causa dell'ordine di precedenza , il postfix si ++verifica prima += , ma il risultato finisce per non essere utilizzato (poiché viene utilizzato il valore precedente di i).


Una decomposizione più accurata delle i += i++parti di cui è fatta richiede che si sappia che entrambi +=e ++non sono atomici (cioè, nessuno dei due è una singola operazione), anche se sembrano come se fossero. Il modo in cui queste vengono implementate comporta variabili temporanee, copie iprima che avvengano le operazioni, una per ogni operazione. (Userò i nomi iAdde iAssignper le variabili temporanee usate per ++e +=rispettivamente).

Quindi, un'approssimazione più vicina a ciò che sta accadendo sarebbe:

int i = 0;
int iAdd = i; // Copy of the current value of i, for ++
int iAssign = i; // Copy of the current value of i, for +=

i = i + 1; // i++ - Happens before += due to order of precedence
i = iAdd + iAssign;

3
@Oded L' ++operazione viene eseguita prima del completamento della valutazione dell'istruzione . Quindi +=sovrascrive il valore. È quello che è successo?
Anirudh Ramanathan,

6
@Oded in realtà la sua: int i = 0; i = i + 1; (postfix) i = 0; (assignment). Se avessi usato altrove in quell'affermazione, avrebbe valutato 1 al momento.
trascina il

@Cthulhu - Essenzialmente. La risposta di dtb va nei dettagli.
Oded,

6
Non compro questo. La risposta di @yoriy è molto più accurata. Per uno, nella tua risposta, dici che l'ultima riga sarebbe i+1mentre dovrebbe essere i=i+1. Non è quello che i++è?
Richiama il

3
La prima parte della risposta è ridondante. Il tuo ultimo esempio di codice avrebbe potuto farlo IMHO. +1 però.
corazza,
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.