¿Por qué "++ i ++" no es válido mientras que (++ i) ++ es válido?


14

Consideremos el siguiente código:

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

Se compila con lo siguiente con un error:

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

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

    3 |     int b = ++i++;

      |                ^~

Esto me parece justo. El incremento de postfix tiene mayor prioridad que el incremento de prefijo, por lo que el código se analiza int b = ++(i++);y ies un valor r. De ahí el error.

Consideremos ahora esta variante con paréntesis para anular las prioridades predeterminadas:

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

Este código compila y devuelve 3. Por sí solo, esto me parece justo, pero parece estar en contradicción con el primer código.

La pregunta: ¿por qué (++i)es un lvaluecuándo ino?

¡Gracias!

ACTUALIZACIÓN: el mensaje de error que se muestra arriba era de gcc (x86-64 9.2). Aquí está la representación exacta: error con gcc

Clang x86-64 9.0.0 tiene un mensaje bastante diferente: error con clang

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

    int b = ++i++;

            ^ ~~~

Con GCC, tiene la impresión de que el problema está en el operador de postfix y luego puede deambular por qué ++iestá bien y ino, de ahí mi pregunta. Con Clang es más claro que el problema está en el operador de prefijo.


Esto fue originalmente etiquetado con C, ciertamente no es válido C.
— Antti Haapala

De hecho lo siento! Supuse que el comportamiento era el mismo en C ...
— Bktero

Respuestas:


23

iy ++ison ambos valores, pero i++es un valor.

++(i++)no puede ser válido, ya que ++se está aplicando el prefijo i++, que es un valor r. Pero (++i)++está bien porque ++ies un valor.

Tenga en cuenta que en C, la situación es diferente; i++y ++ison ambos valores. (Este es un ejemplo de por qué las personas deberían dejar de asumir que C y C ++ tienen las mismas reglas. Las personas insertan estos supuestos en sus preguntas, que luego deben ser refutadas).


4

Esta declaración

int b = ++i++;

es equivalente a

int b = ++( i++ );

El operador de incremento de postfix devuelve el valor del operando antes del incremento.

Del estándar C ++ 17 (8.2.6 Incremento y disminución)

1 El valor de una expresión postfix ++ es el valor de su operando ... El resultado es un prvalue .

Mientras que el operador de incremento unario devuelve lvalue después de su incremento. Entonces esta declaración

int b = (++i)++;

es válida. Podrías por ejemplo escribir

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

Del estándar C ++ 17 (8.3.2 Incremento y decremento)

1 El operando del prefijo ++ se modifica agregando 1. El operando será un valor l modificable. El tipo del operando será un tipo aritmético distinto de cv bool, o un puntero a un tipo de objeto completamente definido. El resultado es el operando actualizado; es un valor de l , y es un campo de bits si el operando es un campo de bits ...

Tenga en cuenta que en C los dos operadores devuelven un valor en lugar de lvalue. Entonces en C esta declaración

int b = (++i)++;

es inválido.


3

entonces el código se analiza como int b = ++ (i ++); y yo soy un valor

No. ino es un valor. ies un valor i++es un rvalue (prvalue para ser específico).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.