Perché "++ i ++" non è valido mentre (++ i) ++ è valido?


14

Consideriamo il seguente codice:

int main() {
    int i = 2;
    int b = ++i++;
    return 3;
}

Si compila con il seguente con un errore:

<source>: In function 'int main()':

<source>:3:16: error: lvalue required as increment operand

    3 |     int b = ++i++;

      |                ^~

Mi sembra giusto. L'incremento Postfix ha una priorità maggiore rispetto all'incremento del prefisso, quindi il codice viene analizzato come int b = ++(i++);ed iè un valore. Da qui l'errore.

Consideriamo ora questa variante con parentesi per sovrascrivere le priorità predefinite:

int main() {
    int i = 2;
    int b = (++i)++;
    return 3;
}

Questo codice viene compilato e restituito 3. Di per sé, questo suona giusto per me, ma sembra in contraddizione con il primo codice.

La domanda: perché (++i)un lvaluequando inon lo è?

Grazie!

AGGIORNAMENTO: il messaggio di errore mostrato sopra era di gcc (x86-64 9.2). Ecco il rendering esatto: errore con gcc

Clang x86-64 9.0.0 ha un messaggio abbastanza diverso: errore con clang

<source>:3:13: error: expression is not assignable

    int b = ++i++;

            ^ ~~~

Con GCC, hai l'impressione che il problema sia con l'operatore postfix e puoi quindi vagare perché ++iva bene mentre inon lo è, quindi la mia domanda. Con Clang è più chiaro che il problema riguarda l'operatore prefisso.


Questo era originariamente etichettato con C, sicuramente non è valido C.
Antti Haapala

Davvero dispiaciuto!
Supponevo

Risposte:


23

ie ++isono entrambi valori, ma i++è un valore.

++(i++)non può essere valido, poiché ++viene applicato il prefisso i++, che è un valore. Ma (++i)++va bene perché ++iè un valore.

Si noti che in C la situazione è diversa; i++e ++isono entrambi valori. (Questo è un esempio del perché le persone dovrebbero smettere di presumere che C e C ++ abbiano le stesse regole. Le persone inseriscono questi presupposti nelle loro domande, che devono quindi essere confutate.)


4

Questa dichiarazione

int b = ++i++;

è equivalente a

int b = ++( i++ );

L'operatore di incremento postfix restituisce il valore dell'operando prima dell'incremento.

Dallo standard C ++ 17 (8.2.6 Incremento e decremento)

1 Il valore di un'espressione postfix ++ è il valore del suo operando ... Il risultato è un valore .

Mentre l'operatore di incremento unario restituisce lvalue dopo il suo incremento. Quindi questa dichiarazione

int b = (++i)++;

è valido. Ad esempio potresti scrivere

int b = (++++++++i)++;

Dallo standard C ++ 17 (8.3.2 Incremento e decremento)

1 L'operando del prefisso ++ viene modificato aggiungendo 1. L'operando deve essere un valore modificabile. Il tipo di operando deve essere un tipo aritmetico diverso da cv bool o un puntatore a un tipo di oggetto completamente definito. Il risultato è l'operando aggiornato; è un lvalue ed è un campo bit se l'operando è un campo bit ....

Prestare attenzione al fatto che in C entrambi gli operatori restituiscono un valore anziché un valore. Quindi in C questa dichiarazione

int b = (++i)++;

è invalido.


3

quindi il codice viene analizzato come int b = ++ (i ++); e io è un valore.

No. inon è un valore. iè un valore. i++è un valore (il valore deve essere specifico).

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.