2009-10-02 16 views
26

Half jokingly half serious : Perché non riesco a eseguire ++i++ in lingue simili a C, in particolare in C#?Perché non riesco a fare ++ i ++ in lingue simili a C?

Mi aspetterei che incrementi il ​​valore, lo usi nella mia espressione, quindi incrementa di nuovo.

+37

Anche se non lavoro, non si dovrebbe, perché non si deve odiare la vita: (Vedendo ++ i ++ mi renderebbe triste in qualsiasi contesto, a prescindere dalla spiegazione – Malaxeur

+0

Non posso, e non dovrei. – luke

+1

Non sapevo che ci fosse il tag "stupido operatore-trucchi", grazie John! – zvolkov

risposta

57

Risposta breve: i++ non è un "lvalue", quindi non può essere oggetto di un incarico.

+3

post-incremento ha la precedenza su pre-incremento; vuoi dire che 'i ++' non è un lvalue, non '++ i'. (Anche se non funziona in entrambi i casi) –

+13

'++ i' è un lvalue, quindi' (++ i) ++ 'sarebbe valido ma per il fatto che scrive in' i' due volte senza un punto di sequenza intermedio . Il problema è che la grammatica specifica che '++ i ++' è equivalente a '++ (i ++)'. –

+0

@Charles Bailey: ++ i è un lvalue in C e C++, ma IIRC non in C#. –

18

Perché ci si preoccupa che un programmatore successivo mantenga (o tenti di riscrivere) il proprio codice, molto tempo dopo che si è licenziati per sfidare le convenzioni popolari.

+2

Ecco perché è "immorale", ma in realtà è illegale oltre che immorale. –

+3

sfortunatamente un sacco di C++ (si spera che venga risolto nel prossimo standard) sono immorali e politicamente scorretti da usare, eppure legale ... – vehomzzz

+0

questo è un commento relativo al design di un programma, più che relativo al design di una lingua. .. – DanM

3

Credo che l'operatore di incremento (o decremento) abbia bisogno di un lvalue da assegnare a. Comunque ++ i non è un lvalue, è un'espressione. Qualcuno esperto in compilatori potrebbe essere in grado di chiarire se c'è qualche motivo tecnico per questo vincolo.

+1

Il tipo di ++ i * è * un lvalue in C. –

+0

Potrebbe chiarire questo un po '? Ho provato a compilare "++ i = 4;" e ricevi un errore che dice che è richiesto un lvalue nella parte sinistra dell'operando. Forse il mio fraintendimento è nella definizione di lvalue? Ho capito che potrebbe essere qualcosa che potrebbe essere assegnato a. – nall

+3

Sezione 5.3.2 dello standard, paragrafo 1: "Il valore è il nuovo valore dell'operando, è un lvalue." (Questo è ovviamente il paragrafo su "prefisso ++".) Naturalmente, "++ i = 4;" è anche un tentativo di cambiare il valore di i due volte senza un punto di sequenza intermedio, e quindi un comportamento indefinito. "f (++ i)" con "int f (int &)" implicherebbe un punto di sequenza e dovrebbe essere legale. –

6

Perché il risultato di i++ non è un lvalue.

+0

++ Sarò valutato per primo. –

+6

post-incremento ha la precedenza, in realtà. –

3

Dalla sezione 7.5.9 della C# 3.0 specification:

L'operando di un incremento suffisso o funzionamento decremento deve essere un espressione classificato come una variabile, un accesso proprietà o un indicizzatore accesso. Il risultato dell'operazione è un valore dello stesso tipo dell'operando. Se l'operando di un incremento postfisso o l'operazione di decremento è una proprietà o l'accesso dell'indicizzatore , la proprietà o l'indicizzatore deve avere sia un get sia un set accessor. Se questo non è il caso, si verifica un errore in fase di compilazione .

Inoltre, l'espressione post-incremento (i++) sarà valutata prima perché ha una priorità più alta rispetto all'operatore pre-incremento (++i).

84

Anche se la risposta breve "non è un lvalue" è corretta, questo è forse solo supplicando la domanda. Perché non è un lvalue? Oppure, come diciamo in C#, una variabile .

Il motivo è perché non puoi avere la tua torta e mangiarla anche. Esegui logicamente:

Prima di tutto, il significato di un operatore ++ in C#, se postfix o prefisso, è "prende il valore di questa variabile, incrementa il valore, assegna il nuovo valore alla variabile e come risultato ". Il valore prodotto come risultato è il valore originale o il valore incrementato, a seconda che si tratti di un suffisso o di un prefisso. Ma in entrambi i casi, produci un valore.

Secondo, il valore di una variabile è sempre il contenuto corrente di tale variabile. (Modulo certi bizzarri scenari di threading che ci porterebbero molto lontano.)

Spero tu sia d'accordo che queste sono regole perfettamente sensate.

Ora dovrebbe essere chiaro il motivo per cui il risultato di I ++ non può essere una variabile, ma nel caso in cui non lo è, mi permetta di mettere in chiaro:

suppongo sia 10. Il significato di i ++ dovrebbe essere "get il valore di i - 10 - incrementalo - 11 - memorizzalo - i è ora 11 - e dai il valore originale come risultato - 10 ". Quindi quando dici print (i ++) dovrebbe stampare 10, e 11 dovrebbe essere memorizzato in i.

Ora supponiamo che il significato di i ++ è quello di restituire la variabile, non il valore. Dici print (i ++) e cosa succede? Ottieni il valore di i - 10 - incrementalo - 11 - memorizzalo - ora sono 11 - e restituisci la variabile come risultato. Qual è il valore corrente della variabile? 11! Che è esattamente quello che NON vuoi stampare.

In breve, se i ++ ha restituito una variabile, sarebbe esattamente il contrario del significato previsto dell'operatore! La tua proposta è logicamente incoerente, motivo per cui nessuna lingua lo fa in questo modo.

+1

In realtà si suppone che l'incremento preliminare incrementi il ​​valore e restituisca un riferimento all'oggetto originale non un valore. –

+3

Bella spiegazione – peacedog

+4

Martin, la mia spiegazione è precisa e precisa; Sto parlando della semantica C#, non della semantica C o C++, perché questo è ciò che il poster originale ha specificamente chiesto. Lo renderò più chiaro nel testo. –

8

ho provato (++ i, i ++) come una soluzione:

#include <stdio.h> 

int main(){ 
    int i=0; 

    printf(" i:   %i\n", i  ); 
    printf(" (++i,i++): %i\n", (++i,i++)); 
    printf(" i:   %i\n", i  ); 
} 

Risultato:


i:   0 
(++i,i++): 1 
i:   2 
+8

I miei occhi, i miei occhi! – RJFalconer

+0

+1 per soluzione alternativa che mantiene la simmetria. – cobbal

+0

Sembra una specie di emoticon. L'oca di abete che vola sottosopra? –

Problemi correlati