c++ - Por que "++ i++" é inválido enquanto(++ i)++ é válido?




operators lvalue (2)

portanto, o código é analisado como int b = ++ (i ++); e i é um rvalor.

Não. i não é um rvalor. i sou um valor. i++ é um rvalue (prvalue para ser específico).

Vamos considerar o seguinte código:

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

Ele é compilado com o seguinte com um erro:

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

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

    3 |     int b = ++i++;

      |                ^~

Isso parece justo para mim. O incremento do Postfix tem prioridade mais alta que o incremento do prefixo; portanto, o código é analisado como int b = ++(i++); e i é um rvalor. Daí o erro.

Vamos agora considerar esta variante entre parênteses para substituir as prioridades padrão:

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

Esse código compila e retorna 3. Por si só, isso me parece justo, mas parece contraditório com o primeiro código.

A pergunta: por que (++i) é um valor i quando i não sou?

Obrigado!

UPDATE: a mensagem de erro mostrada acima era do gcc (x86-64 9.2). Aqui está a renderização exata: error with gcc

Clang x86-64 9.0.0 tem uma mensagem bem diferente: erro com clang

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

    int b = ++i++;

            ^ ~~~

Com o GCC, você tem a impressão de que o problema está no operador postfix e, em seguida, você pode pensar por que ++i está OK enquanto i não i , daí a minha pergunta. Com o Clang, fica mais claro que o problema está no operador de prefixo.


Esta declaração

int b = ++i++;

é equivalente a

int b = ++( i++ );

O operador de incremento postfix retorna o valor do operando antes do incremento.

Do padrão C ++ 17 (8.2.6 Incremento e decremento)

1 O valor de uma expressão postfix ++ é o valor de seu operando ... O resultado é um prvalor .

Enquanto o operador de incremento unário retorna lvalue após seu incremento. Então esta declaração

int b = (++i)++;

é válido. Você poderia, por exemplo, escrever

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

Do padrão C ++ 17 (8.3.2 Incremento e decremento)

1 O operando do prefixo ++ é modificado adicionando 1. O operando deve ser um lvalue modificável. O tipo do operando deve ser um tipo aritmético que não seja cv bool ou um ponteiro para um tipo de objeto completamente definido. O resultado é o operando atualizado; é um lvalue e é um campo de bits se o operando for um campo de bits ....

Preste atenção que em C os dois operadores retornam um valor em vez de lvalue. Então em C esta declaração

int b = (++i)++;

é inválido.







pre-increment