Después de investigar, leí que el operador de incremento requiere que el operando tenga un objeto de datos modificable: https://en.wikipedia.org/wiki/Increment_and_decrement_operators .
De esto, supongo que da un error de compilación porque (a+b)
es un número entero temporal y, por lo tanto, no es modificable.
¿Es correcto este entendimiento? Esta fue la primera vez que intenté investigar un problema, por lo que si había algo que debería haber buscado, avíseme.
c = a + b + 1
hace que tu intención sea más clara y también es más corta de escribir. Los operadores de incremento / decremento hacen dos cosas: 1. ellos y su argumento forman una expresión (que se puede usar, por ejemplo, en un bucle for), 2. modifican el argumento. En su ejemplo, está usando la propiedad 1. pero no la propiedad 2., ya que descarta el argumento modificado. Si no necesita la propiedad 2. y solo desea la expresión, puede escribir una expresión, por ejemplo, x + 1 en lugar de x ++.Respuestas:
Es solo una regla, eso es todo, y posiblemente esté ahí para (1) facilitar la escritura de compiladores de C y (2) nadie ha convencido al comité de estándares de C para que lo relaje.
Hablando informalmente, solo puede escribir
++foo
sifoo
puede aparecer en el lado izquierdo de una expresión de asignación comofoo = bar
. Como no puedes escribira + b = bar
, tampoco puedes escribir++(a + b)
.No hay ninguna razón real por la que
a + b
no pueda producir un temporal en el que++
pueda operar, y el resultado de eso es el valor de la expresión++(a + b)
.fuente
++
veces tuviera el efecto secundario de modificar algo y otras veces simplemente no.El estándar C11 establece en la sección 6.5.3.1
Y el "valor modificable" se describe en la sección 6.3.2.1 subsección 1
Por
(a+b)
lo tanto, no es un lvalue modificable y, por lo tanto, no es elegible para el operador de incremento de prefijo.fuente
Estás en lo correcto. la
++
trata de asignar el nuevo valor a la variable original. Entonces++a
tomará el valor dea
, lo agregará1
y luego lo volverá a asignara
. Como, como dijiste, (a + b) es un valor temporal y no una variable con una dirección de memoria asignada, la asignación no se puede realizar.fuente
Creo que en su mayoría respondiste a tu propia pregunta. Podría hacer un pequeño cambio en su fraseo y reemplazar "variable temporal" con "rvalue" como mencionó C.Gibbons.
Los términos variable, argumento, variable temporal, etc. se volverán más claros a medida que aprenda sobre el modelo de memoria de C (esto parece una buena descripción general: https://www.geeksforgeeks.org/memory-layout-of-c-program/ ).
El término "rvalue" puede parecer opaco cuando recién está comenzando, así que espero que lo siguiente ayude a desarrollar una intuición al respecto.
Lvalue / rvalue se refieren a los diferentes lados de un signo igual (operador de asignación): lvalue = lado izquierdo (L minúscula, no "uno") rvalue = lado derecho
Aprender un poco sobre cómo C usa la memoria (y los registros) será útil para ver por qué la distinción es importante. Con pinceladas amplias , el compilador crea una lista de instrucciones en lenguaje de máquina que calculan el resultado de una expresión (el rvalue) y luego coloca ese resultado en algún lugar (el lvalue). Imagine un compilador que se ocupa del siguiente fragmento de código:
En el pseudocódigo de ensamblaje, podría parecerse a este ejemplo de juguete:
El operador ++ (y su - contraparte) necesita un "lugar" para modificar, esencialmente cualquier cosa que pueda funcionar como un lvalue.
Comprender el modelo de memoria C será útil porque obtendrá una mejor idea en su cabeza sobre cómo se pasan los argumentos a las funciones y (eventualmente) cómo trabajar con la asignación de memoria dinámica, como la función malloc (). Por razones similares, podría estudiar alguna programación simple en ensamblador en algún momento para tener una mejor idea de lo que está haciendo el compilador. Además, si está utilizando gcc , la opción -S "Deténgase después de la etapa de compilación propiamente dicha; no ensamble". puede ser interesante (aunque recomiendo probarlo en un pequeño fragmento de código).
Solo como un aparte: la instrucción ++ ha existido desde 1969 (aunque comenzó en el predecesor de C, B):
Seguir esa referencia de wikipedia lo llevará a un artículo interesante de Dennis Ritchie (la "R" en "K&R C") sobre la historia del lenguaje C, vinculado aquí para su conveniencia: http://www.bell-labs.com/ usr / dmr / www / chist.html donde puede buscar "++".
fuente
La razón es que el estándar requiere que el operando sea un valor l. La expresión
(a+b)
no es un lvalue, por lo que no se permite aplicar el operador de incremento.Ahora, se podría decir "OK, que es de hecho la razón, pero en realidad no hay * real * razón aparte de eso" , pero por desgracia la formulación particular de cómo funciona el operador de hecho no requerir que ser el caso.
Obviamente, no puede escribir
E += 1
siE
no es un lvalue. Lo cual es una lástima porque también se podría haber dicho: "incrementa E en uno" y listo. En ese caso, aplicar el operador en un valor distinto de l sería (en principio) perfectamente posible, a costa de hacer que el compilador sea un poco más complejo.Ahora, la definición podría reformularse trivialmente (creo que ni siquiera es originalmente C, sino una reliquia de B), pero hacerlo cambiaría fundamentalmente el lenguaje a algo que ya no es compatible con sus versiones anteriores. Dado que el posible beneficio es bastante pequeño pero las posibles implicaciones son enormes, eso nunca sucedió y probablemente nunca sucederá.
Si considera C ++ además de C (la pregunta está etiquetada como C, pero hubo una discusión sobre las sobrecargas de operadores), la historia se vuelve aún más complicada. En C, es difícil imaginar que este podría ser el caso, pero en C ++ el resultado de
(a+b)
podría muy bien ser algo que no se puede incrementar en absoluto, o incrementar podría tener efectos secundarios muy considerables (no solo agregar 1). El compilador debe poder hacer frente a eso y diagnosticar los casos problemáticos a medida que ocurren. En un valor, todavía es un poco trivial comprobarlo. No es así para cualquier tipo de expresión fortuita entre paréntesis que le arrojes al pobre.Esta no es una razón real por la que no podría Se puede hacer, pero sin duda sirve como explicación de por qué las personas que implementaron esto no están precisamente encantadas de agregar una característica que promete muy pocos beneficios a muy pocas personas.
fuente
(a + b) evalúa a un rvalue, que no se puede incrementar.
fuente
++ intenta dar el valor a la variable original y dado que (a + b) es un valor temporal, no puede realizar la operación. Y son básicamente reglas de las convenciones de programación de C para facilitar la programación. Eso es.
fuente
Cuando se realiza la expresión ++ (a + b), entonces, por ejemplo:
fuente