2009-10-02 10 views
26

Medio medio en broma grave : ¿Por qué no puedo hacer ++i++ en lenguajes tipo C, específicamente en C#?¿Por qué no puedo hacer ++ i ++ en lenguajes tipo C?

Espero que incremente el valor, use eso en mi expresión, luego incremente de nuevo.

+37

Incluso si lo hizo el trabajo, usted debe no porque no debe odiar la vida: (. Ver ++ ++ me entristecería en cualquier contexto, independientemente de la explicación. – Malaxeur

+0

No puedo, y no debería. – luke

+1

No sabía que existía la etiqueta de "truco de operador estúpido", ¡gracias John! – zvolkov

Respuesta

57

Respuesta corta: i++ no es un "lvalue", por lo que no puede ser objeto de una asignación.

+3

post-incremento tiene prioridad sobre el pre-incremento; quieres decir que 'i ++' no es un lvalue, no '++ i'. (Aunque no funciona de ninguna manera) –

+13

'++ i' es un lvalue, por lo que' (++ i) ++ 'sería válido, pero por el hecho de que se escribe en' i' dos veces sin un punto de secuencia intermedio . El problema es que la gramática especifica que '++ i ++' es equivalente a '++ (i ++)'. –

+0

@Charles Bailey: ++ i es un lvalue en C y C++, pero IIRC no en C#. –

18

Porque te importa que un próximo programador mantenga (o intente reescribir) tu código, mucho después de que te despidan por desafiar las convenciones populares.

+2

Es por eso que es "inmoral", pero de hecho es ilegal e inmoral. –

+3

desafortunadamente, muchos C++ (con suerte para ser corregidos en el próximo estándar) son inmorales y políticamente incorrectos, pero legales ... – vehomzzz

+0

es un comentario relacionado con el diseño de un programa, más que relacionado con el diseño de un idioma. .. – DanM

3

Creo que el operador de incremento (o decremento) necesita un valor l para asignar. Sin embargo, ++ i no es un valor l, es una expresión. Alguien mejor versado en compiladores podría aclarar si hay alguna razón técnica para esta restricción.

+1

El tipo de ++ i * es * un lvalue en C. –

+0

¿Podría aclarar esto un poco? Traté de compilar "++ i = 4;" y recibe un error que dice que se requiere un lvalor en la mano izquierda del operando. Tal vez mi malentendido está en la definición de lvalue? Entendí que era algo a lo que podía asignárseme. – nall

+3

Sección 5.3.2 de la norma, párrafo 1: "El valor es el nuevo valor del operando; es un valor l". (Este es, por supuesto, el párrafo sobre "prefijo ++"). Por supuesto, "++ i = 4;" también es un intento de cambiar el valor de i dos veces sin un punto de secuencia intermedio, y por lo tanto un comportamiento indefinido. "f (++ i)" con "int f (int &)" implicaría un punto de secuencia y debería ser legal. –

6

Porque el resultado de i++ no es un valor l.

+0

++ Sería evaluado primero. –

+6

post-incremento tiene prioridad, en realidad. –

3

De la sección 7.5.9 de la C# 3.0 specification:

El operando de un incremento de sufijo o operación de decremento debe ser una expresión clasificada como una variable, un acceso propiedad, o un acceso indexador. El resultado de la operación es un valor del mismo tipo que el operando. Si el operando de un incremento de posfijo o operación de reducción es una propiedad o acceso del indexador , la propiedad o el indexador debe tener un acceso get y . Si no es el caso, se produce un error de tiempo de compilación .

Además, la expresión de incremento posterior (i++) sería evaluado primero porque tiene una prioridad más alta que el (++i) operador de incremento previo.

84

Aunque la respuesta corta "no es un lvalue" es correcta, eso tal vez sea la mera pregunta. ¿Por qué no es un lvalue? O, como decimos en C#, una variable .

La razón es porque no puedes tener tu pastel y comértelo también. Resuélvase lógicamente:

Primero, el significado de un operador ++ en C#, ya sea postfix o prefijo, es "tome el valor de esta variable, incremente el valor, asigne el nuevo valor a la variable, y producir un valor como resultado ". El valor producido como resultado es el valor original o el valor incrementado, dependiendo de si se trata de un sufijo o un prefijo. Pero de cualquier forma, produces un valor.

Segundo, el valor de una variable es siempre el contenido actual de esa variable. (Modulo ciertos escenarios de subprocesos extraños que nos llevarían lejos.)

Espero que estén de acuerdo en que estas son reglas perfectamente razonables.

Ahora debería estar claro por qué el resultado de i ++ no puede ser una variable, pero en caso de no ser así, quiero dejar claro:

supongo que es 10. El significado de i ++ debe ser "llegar el valor de i - 10 - incrementarlo - 11 - almacenarlo - ahora es 11 - y dar como resultado el valor original - 10 ". Entonces cuando dices print (i ++) debería imprimir 10, y 11 debería almacenarse en i.

Supongamos ahora que el significado de i ++ es devolver el variables, no el valor . Usted dice imprimir (i ++) y ¿qué ocurre? Obtienes el valor de i - 10 - lo incrementa - 11 - lo almacena - ahora tengo 11 - y devuelve la variable como resultado. ¿Cuál es el valor actual de la variable? 11! Que es exactamente lo que NO quieres imprimir.

En resumen, si i ++ devolvió una variable, entonces estaría haciendo exactamente lo contrario del significado previsto del operador! Su propuesta es lógicamente inconsistente, por lo que ningún idioma lo hace de esa manera.

+1

En realidad, se supone que el incremento previo incrementa el valor y devuelve una referencia al objeto original, no un valor. –

+3

Buena explicación – peacedog

+4

Martin, mi explicación es precisa y precisa; Estoy hablando de la semántica C#, no de la semántica C o C++, porque eso es lo que el cartel original pedía específicamente. Lo dejaré más claro en el texto. –

8

que probé (++ i, i ++) como solución alternativa:

#include <stdio.h> 

int main(){ 
    int i=0; 

    printf(" i:   %i\n", i  ); 
    printf(" (++i,i++): %i\n", (++i,i++)); 
    printf(" i:   %i\n", i  ); 
} 

Resultado:


i:   0 
(++i,i++): 1 
i:   2 
+8

¡Mis ojos, mis ojos! – RJFalconer

+0

+1 para la solución que mantiene la simetría. – cobbal

+0

Parece una especie de emoticón. ¿El Spruce Goose volando al revés? –

Cuestiones relacionadas