El operador ++ postfijo y el sentido común…

Post cortito… 😉

El otro día estaba revisando código y vi algo parecido a lo siguiente (C#):

int x = 1;
int y = x++;

Si os pregunto los valores de x e y al final de este código… ¿cual seria vuestra respuesta? No lo preguntéis a Visual Studio… pensadlo.

¿Ya lo teneis?

Exacto: x vale 2 (es de esperar puesto que su valor se incrementa con ++), mientras que por su parte y vale 1. Es decir, el valor de x se incrementa después de la asignación.

Quizá os parezca ilógico, pero está así especificado explícitamente en la especificación de C#:

The ++ and -- operators also support prefix notation, as described in Section 7.6.5. The result of x++ or x-- is the value of x before the operation, whereas the result of ++x or --x is the value of x after the operation. In either case, x itself has the same value after the operation.

Sacado de: http://msdn.microsoft.com/en-us/library/aa691363(VS.71).aspx

Ya veis con que cosillas nos divertimos, eh??? 😉

Saludos

PD: De la misma manera (y por la misma razón) en el siguiente código:

int x =1;
x=x++;

x tiene el valor 1 al finalizar.

En C# este código es correcto (otra cosa es que sea útil), a diferencia de p.ej. C++ donde este código es incorrecto: compila pero su resultado no está definido por el estándard… en algunos compiladores x puede terminar valiendo 1 y en otros compiladores puede terminar valiendo 2 (el caso de VC++ 9 en debug).

9 comentarios sobre “El operador ++ postfijo y el sentido común…”

  1. Pues si no me equivoco, el resultado correcto de lo último debería ser 2, al menos en C++ (y me da igual que no esté definido por el estándar).

    x++ es el operador de postincremento. por lo que la sentencia

    x=x++;

    se debe leer como

    (x=x)++;

    Es decir, x se asigna a x, con lo que sigue valiendo 1, y luego se incrementa x, que pasará a valer 2. Ahora bien, ambas x deben ser la misma variable, ya que, por ejemplo, si picamos:

    ::x=x++;

    teniendo en cuenta que el primer x es una variable en un ámbito superior al segundo x, entonces sí, entonces el x exterior valdría 1 y el interior se perdería al salir de ámbito. Algo así:

    int x;
    {
    int x=1;
    ::x=x++;
    }

  2. Si pero se incrementa después de la asignación no?

    Supongo que en el artículo se refiere a que si mostramos el valor de X mostraría 1 pero si mostramos tras el incremento sí mostraría 2.

    Saludos.
    Francisco J.

  3. Hola,
    Gracias a todos por vuestros comentarios 🙂 Lo que da de sí un simple ++, eh??? 😉

    @Javier
    Sí, son cosas curiosas… por eso he puesto lo del «sentido común» en el título del post.

    @Rafa
    Es que todo depende de como interpretas que se traduce x++…

    Comprueba como el siguiente código en C++:
    int x=1;
    int y=1;
    y=x++;

    Te deja en y el valor 1 (no 2). Queda claro pues que el incremento de x se realiza DESPUES de la asignación a y. Y este código es código «legal» y simple…

    Porque entonces x = x++ nos deja 2 en x??? Por coherencia nos debería dejar 1. La razón es simplemente que x=x++ «no es código válido» en C++ y su comportamiento no está definido (algunos compiladores devuelven 2, otros 1).

    @Francisco J
    Efectivamente x, se incrementa DESPUES de la asignación… El «problema» es si hemos hecho la asignación a la propia x 😉
    En el código inicial:

    int x = 1;
    int y = x++;

    y termina valiendo 1 y x termina valiendo 2 🙂

    Saludos!

  4. Buenas a todos!!

    Es curioso, pero lo que es de sentido común es informarnos de cómo está implementada la gramática de C# (o C++ en su caso) en cada compilador, esto es, si se permite o no ese tipo de operaciones, y qué prioridad se da a los operadores, para saber a ciencia cierta qué resultado dará.

    Claro, como dice Eduard, para nosotros es un asunto tonto porque igual no tiene mucha utilidad, por lo que mejor aplicaríamos esto a los que hacen cada uno de los compiladores, esto es, que no se dediquen a usar el sentido común (su subjetivo sentido común) e intenten estandarizar la prioridad de los operadores en todos ellos, no pase como en las antiguas migraciones de C 16 bits a C 32 bits dónde en uno la declaración de string asigna un valor por defecto y en el otro un null.

    Muy bueno el post, pequeñas cositas para distraernos un poco.

  5. @Francisco
    Gracias por tus comentarios… Como dices es algo que no pasa de un mero «divertimento»… pero a mi esas cosillas que tratan sobre aspectos «curiosos» (por poco conocidos, poco intuitivos,…) de los lenguajes me gustan mucho…

    … friki que será uno 😉

    Un abrazo!

  6. Buenas,

    En este post de 2004, el propio Luca Bolognese (miembro del equipo de C#) nos explica de qué forma se evalúan este tipo de operaciones y también qué criterios de diseño condujeron a que funcione de la forma que funciona: http://blogs.msdn.com/lucabol/archive/2004/08/31/223580.aspx

    Creo que es perfectamente lógico y que hay cosas que se deben priorizar en el desarrollo de un lenguaje. También estoy de acuerdo en que si llegas a un caso tan concreto, te puedes volver loco para averiguar qué está pasando. De todos modos, lo que más me sorprende es: ¿ninguna herramienta de análisis de código, tipo FxCop o similar, se quejó al ver una instrucción de ese tipo? «x = x++» es algo que ves y ya tiene mala pinta, en mi opinión.

    Salut,
    M.

  7. @Miguel
    Buenas! 😉

    Leí el post de Luca y es realmente interesante. Evidentemente sus decisiones están totalmente justificadas… Estoy de acuerdo contigo que hay otros temas a priorizar en el desarrollo de un lenguaje!
    De hecho mi post no era una crítica ni a C# (ni a C++), sino simplemente comentar este comportamiento que para muchos puede parecer «anti-intuitivo»… 🙂

    Acavo de probarlo ahora y el código x+=x++; compilado bajo VS2010 y con todas las reglas de análisis estático activado no da ningún warning. FxCop no lo he probado. De todos modos creo que es un error que debe ser relativamente dificil de detectar usando FxCop/Análisis Estático ya que diría que el MSIL generado por este código no debe tener nada especialmente sospechoso…

    Un saludo crack!

  8. Me recuerda a esos artículos académicos donde dicen que los operadores «++» y «–» se deben eliminar completamente (no importa si es pos o pre).

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *