Hai scritto "assumi un linguaggio simile alla C". Solo come C-like dovrebbe essere?
Per prima cosa, sembra che la logica dell'autore sia indietro:
It has the effect of assigning the value of a[1] + 1 to a[2] whenever
the evaluation of the left-hand component of the assignment precedes
the evaluation of the right-hand one.
In effetti, ha questo effetto se la valutazione del LHS segue la valutazione del RHS.
Alcuni linguaggi "simili a C" (nel senso che la loro sintassi assomiglia a quelli di C) definiscono l'ordine di valutazione delle espressioni. (Penso che Java faccia questo.) In un tale linguaggio, la semantica del codice dipenderebbe esattamente da come il linguaggio definisce l'ordine di valutazione. Se l'ordine è da sinistra a destra, la chiamata di funzione sul LHS (lato sinistro) del compito verrà valutata per prima.
In C stesso (e in C ++), l'ordine di valutazione è non specificato . Le due chiamate di funzione potrebbero essere valutate in entrambi gli ordini, a seconda del capriccio del compilatore (l'ottimizzazione può cambiare questo, quindi, in linea di principio, può la fase lunare). Non credo che il comportamento di questo particolare codice sia in realtà indefinito, il che significherebbe che la lingua dice niente su come si comporta, ma un codice simile come:
a[i++] = a[i++] + 1;
ha un comportamento indefinito, perché i
viene modificato due volte senza alcun punto di sequenza intermedio. In C, quanto sopra potrebbe valutare il LHS i++
prima di quello giusto, o viceversa, ma quelle non sono le uniche possibilità. Un compilatore C è libero di assumere che il tuo programma non modifichi i
due volte tra i punti di sequenza. Questo particolare esempio sembra facile da rilevare per il compilatore, ma in casi più complessi può essere difficile o impossibile farlo.
Ma la vera risposta alla domanda è: Non scrivere codice del genere.
In realtà non è necessario avere due chiamate di funzione in una singola istruzione, in cui i risultati dipendono dall'ordine in cui vengono valutati. Separare le chiamate in istruzioni distinte, ad esempio:
int x = f(3);
int y = f(3);
a[x] = a[y] + 1;
E nella vita reale, vuoi nomi migliori di x
, y
, f
e a
- e f()
probabilmente non dovrebbe restituire risultati diversi su chiamate successive, o dovrebbe essere molto chiaro perché ha bisogno di farlo.
Scrivi il tuo codice in modo che domande come questa non si presentino in primo luogo.