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 rvalue. 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 lvalue
quando i
não é?
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, pode perambular por que ++i
está tudo bem enquanto i
não estiver, daí a minha pergunta. Com o Clang, fica mais claro que o problema está no operador de prefixo.
Respostas:
i
e++i
são ambos lvalues, masi++
é um rvalue.++(i++)
não pode ser válido, pois o prefixo++
está sendo aplicadoi++
, que é um rvalue. Mas(++i)++
está bem porque++i
é um valor l.Observe que em C, a situação é diferente;
i++
e++i
são ambos os valores. (Este é um exemplo de por que as pessoas devem parar de supor que C e C ++ têm as mesmas regras. As pessoas inserem essas suposições em suas perguntas, que devem ser refutadas.)fonte
Esta declaração
é equivalente a
O operador de incremento postfix retorna o valor do operando antes do incremento.
Do padrão C ++ 17 (8.2.6 Incremento e decremento)
Enquanto o operador de incremento unário retorna lvalue após seu incremento. Então esta declaração
é válido. Você poderia, por exemplo, escrever
Do padrão C ++ 17 (8.3.2 Incremento e decremento)
Preste atenção que em C os dois operadores retornam um valor em vez de lvalue. Então em C esta declaração
é inválido.
fonte
No.
i
não é um rvalue.i
é um valor l.i++
é um rvalue (prvalue para ser específico).fonte