Non è definito perché modifica x
due volte tra i punti di sequenza. Lo standard dice che è indefinito, quindi non è definito.
Questo lo so.
Ma perché?
La mia comprensione è che vietare ciò consente ai compilatori di ottimizzare meglio. Questo avrebbe potuto avere senso quando C fu inventato, ma ora sembra un argomento debole.
Se dovessimo reinventare C oggi, lo faremmo in questo modo, o si potrebbe fare meglio?
O forse c'è un problema più profondo, che rende difficile definire regole coerenti per tali espressioni, quindi è meglio vietarle?
Quindi supponiamo di reinventare C oggi. Vorrei suggerire regole semplici per espressioni come x=x++
, che mi sembrano funzionare meglio delle regole esistenti.
Mi piacerebbe avere la tua opinione sulle regole suggerite rispetto a quelle esistenti o altri suggerimenti.
Regole suggerite:
- Tra punti di sequenza, l'ordine di valutazione non è specificato.
- Gli effetti collaterali avvengono immediatamente.
Non sono coinvolti comportamenti indefiniti. Le espressioni valutano questo valore o quello, ma sicuramente non formatteranno il tuo hard disk (stranamente, non ho mai visto un'implementazione dove x=x++
formatta il disco rigido).
Espressioni di esempio
-
x=x++
- Ben definito, non modificax
.
Innanzitutto,x
viene incrementato (immediatamente quando viene valutatox++
), quindi il suo vecchio valore è memorizzato inx
. -
x++ + ++x
- Incrementix
due volte, restituisce2*x+2
.
Sebbene entrambi i lati possano essere valutati per primi, il risultato èx + (x+2)
(lato sinistro prima) o(x+1) + (x+1)
(lato destro prima). -
x = x + (x=3)
- Non specificato,x
impostato sux+3
o6
.
Se il lato destro viene valutato per primo, èx+3
. È anche possibile chex=3
sia valutato per primo, quindi è3+3
. In entrambi i casi, l'assegnazione dix=3
avviene immediatamente quando viene valutatox=3
, quindi il valore memorizzato viene sovrascritto dall'altra assegnazione. -
x+=(x=3)
- Ben definito, impostax
su 6.
Si potrebbe sostenere che questa è solo una scorciatoia per l'espressione sopra.
Ma direi che+=
deve essere eseguito dopox=3
, e non in due parti (leggix
, valutax=3
, aggiungi e memorizza nuovo valore).
Qual è il vantaggio?
Alcuni commenti hanno sollevato questo buon punto.
Certamente non penso che espressioni come x=x++
debbano essere usate in qualsiasi codice normale.
In realtà, sono molto più severo di così: penso che l'unico utilizzo valido per x++
sia in x++;
.
Tuttavia, penso che le regole linguistiche debbano essere il più semplici possibile. Altrimenti i programmatori semplicemente non li capiscono. la regola che vieta di cambiare una variabile due volte tra i punti di sequenza è certamente una regola che molti programmatori non capiscono.
Una regola molto semplice è questa:
Se A è valido e B è valido e sono combinati in modo valido, il risultato è valido.
x
è un valore L valido, x++
è un'espressione valida e =
è un modo valido per combinare un valore L e un'espressione, quindi come mai x=x++
non è legale?
Lo standard C fa un'eccezione qui e questa eccezione complica le regole. Puoi cercare stackoverflow.com e vedere quanto questa eccezione confonde le persone.
Quindi dico: sbarazzati di questa confusione.
=== Riepilogo delle risposte ===
-
Perché farlo?
Ho cercato di spiegare nella sezione precedente: voglio che le regole C siano semplici. -
Potenziale di ottimizzazione:
Ciò richiede una certa libertà dal compilatore, ma non ho visto nulla che mi abbia convinto che potrebbe essere significativo.
La maggior parte delle ottimizzazioni può ancora essere fatta. Ad esempio,a=3;b=5;
può essere riordinato, anche se lo standard specifica l'ordine. Espressioni comea=b[i++]
possono ancora essere ottimizzate allo stesso modo.
-
Non è possibile modificare lo standard esistente.
Lo ammetto, non posso. Non ho mai pensato di poter effettivamente andare avanti e cambiare standard e compilatori. Volevo solo pensare se le cose avrebbero potuto essere fatte in modo diverso.