{"id":1184,"date":"2010-06-21T17:26:07","date_gmt":"2010-06-21T15:26:07","guid":{"rendered":"http:\/\/www.tiendadeultramarinos.es\/?p=1184"},"modified":"2010-06-21T18:24:36","modified_gmt":"2010-06-21T16:24:36","slug":"incremento-y-decremento","status":"publish","type":"post","link":"https:\/\/www.tiendadeultramarinos.es\/?p=1184","title":{"rendered":"Incremento y decremento"},"content":{"rendered":"<p>Hoy toca post para inform\u00e1ticos. Como bien sabr\u00e9is, muchos lenguajes disponen de una forma abreviada de indicar incrementos y decrementos, que son &#8216;<code>++<\/code>&#8216; y &#8216;<code>--<\/code>&#8216;. Esto, adem\u00e1s de facilitar la vida a los programadores evit\u00e1ndoles escribir <code>a=a+1<\/code>, es tambi\u00e9n de utilidad para las optimizaciones que hace el compilador, puesto que en la mayor\u00eda de arquitecturas existen instrucciones de incremento y decremento que se ejecutan utilizando menos recursos que una suma convencional.<\/p>\n<p>En algunos lenguajes, como en C y Java, se puede utilizar este operador delante y detr\u00e1s de las variables, <strong>pero tiene un comportamiento distinto<\/strong>. Si el operador est\u00e1 delante, se hace primero la resta y se eval\u00faa el resultado; mientras que si est\u00e1 detr\u00e1s, primero se devuelve el valor, y despu\u00e9s se realiza la resta.<\/p><a name=\"teMiddle488558617\"><\/a><div class=\"te_div\" id=\"te488558617\">\n<p>As\u00ed, si <em>b=10<\/em> y hacemos <code>a=--b<\/code>, <em>a<\/em> y <em>b<\/em> terminar\u00e1n con valor 9, pero <code>a=b--<\/code> terminar\u00e1 con <code>a=10<\/code> y <code>b=9<\/code>.<\/p>\n<p>Bien, recordado esto, en mis apuntes de compiladores se menciona como un c\u00f3digo algo lioso a primera vista, la siguiente instrucci\u00f3n <code>c=a---b--<\/code>. A ra\u00edz de ello, he decidido pensar en\u00a0 situaciones similares a \u00e9sta, que son:<\/p>\n<blockquote><p><code>c = --a---b;<br \/>\nc = --a-b--;<br \/>\nc = a-----b;<br \/>\nc = a---b--;<br \/>\nc = a---b;<\/code><\/p><\/blockquote>\n<p>Suponiendo que es ilegal <code>--n--<\/code>, y obviando la \u00faltima (hay que acordar c\u00f3mo se comporta) \u00bfAlguien se anima a hacer la traza? Es facilita, la hice ayer a mano en lugar de seguir estudiando :P.<\/p>\n<p>Aunque todas salvo la \u00faltima parezcan correctas y sin ambig\u00fcedades, curiosamente hay dos de ellas que ni C ni Java aceptan (con los compiladores GCC 2.8.1, Borlandc 3.0 y JDK 1.6). Son la primera y la tercera, y ocurre lo mismo si en lugar de &#8216;<code>--<\/code>&#8216; utilizamos &#8216;<code>++<\/code>&#8216;. \u00bfPor qu\u00e9? Pues imagino que por el tipo de an\u00e1lisis que hace el compilador.<\/p>\n<p>Tal y como veo que se comporta (he hecho m\u00e1s pruebas aparte de esos 5 casos), cuando el analizador l\u00e9xico lee el c\u00f3digo car\u00e1cter a car\u00e1cter, siempre que encuentra dos &#8216;-&#8216; seguidos, los considera un \u00fanico token &#8216;<code>--<\/code>&#8216; y as\u00ed es como los env\u00eda al siguiente nivel.<\/p>\n<p>Despu\u00e9s, en el analizador sint\u00e1ctico\/sem\u00e1ntico debe de existir alg\u00fan tipo de precedencia asignada al operador &#8216;<code>--<\/code>&#8216; por encima de la resta y el opuesto, de modo que cuando se encuentra con <code>--a<\/code>, \u00f3 <code>a--<\/code>, hace directamente una reducci\u00f3n y pasa a considerar la expresi\u00f3n como una constante, a la que ya no tiene sentido volver a aplicar otro &#8216;<code>--<\/code>&#8216;.<\/p>\n<p>En el caso \u00abespecial\u00bb <code>c=a---b<\/code>, a mi juicio el \u00fanico que es ambiguo y del que deber\u00eda quejarse el compilador, se opta por aplicar el operador &#8216;<code>--<\/code>&#8216; a la variable <em>a<\/em>; siendo equivalente a ejecutar <code>c=a-b<\/code> y despu\u00e9s <code>a--<\/code>.<\/p>\n<p>Tambi\u00e9n acepta correctamente <code>c=-a--;<\/code> \/\/ c = -a (y decrementar despu\u00e9s a).<\/p>\n<p>Otras asignaciones que dan error de compilaci\u00f3n, y comentado a lo que deber\u00eda corresponder:<\/p>\n<blockquote><p><code>c = ---a; <\/code>\/\/c = &#8211; (decremento de a)<\/p>\n<p><code>c = --a--b;<\/code> \/\/c = (decremento de a) menos (-b)<\/p>\n<p><code>c = a--b;<\/code> \/\/ c = a menos (-b)<\/p>\n<p><code>c = a----b;<\/code> \/\/ c = a menos (-b) [y despu\u00e9s decrementar a]<\/p><\/blockquote>\n<p>Por los errores que da el compilador, en el primer caso creo que intentar aplicar el operador &#8216;<code>--<\/code>&#8216; sobre &#8216;<code>-<\/code>&#8216;, y en el tercer caso, evalua &#8216;<code>a--<\/code>&#8216;, y despu\u00e9s encuentra la <em>b<\/em> sin operadores entre ellos. En el segundo fallan dos cosas: primero aplica correctamente <code>--a<\/code>, pero al resultado no se le puede aplicar otra vez &#8216;<code>--<\/code>&#8216;; el segundo fallo es que ha consumido el token &#8216;<code>--<\/code>&#8216; y se encuentra, de nuevo, con una <em>b<\/em> solitaria sin operadores entre la <em>a<\/em>. En el cuarto tenemos otros dos fallos similares al anterior.<\/p>\n<p>\u00bfOcurrir\u00e1 as\u00ed en todos los compiladores de C, o habr\u00e1n tenido esto en cuenta en alg\u00fan caso? \u00bfO es algo definido directamente en el est\u00e1ndar? He echado un vistazo r\u00e1pido al ANSI C buscando \u00abdecrement\u00bb, pero no he le\u00eddo nada destacable.<\/p>\n<\/div><p style=\"text-align: center;\"><a style=\"display:none;\" class=\"theTag\" id=\"te488558617\" onClick=\"expand('#te488558617');\" href=\"#teMiddle488558617\"><\/a><\/p><script language=\"JavaScript\" type=\"text\/javascript\">expander_hide('#te488558617');<\/script>","protected":false},"excerpt":{"rendered":"<p>Hoy toca post para inform\u00e1ticos. Como bien sabr\u00e9is, muchos lenguajes disponen de una forma abreviada de indicar incrementos y decrementos, que son &#8216;++&#8216; y &#8216;&#8211;&#8216;. Esto, adem\u00e1s de facilitar la vida a los programadores evit\u00e1ndoles escribir a=a+1, es tambi\u00e9n de utilidad para las optimizaciones que hace el compilador, puesto que en la mayor\u00eda de arquitecturas &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.tiendadeultramarinos.es\/?p=1184\" class=\"more-link\">Seguir leyendo<span class=\"screen-reader-text\"> \u00abIncremento y decremento\u00bb<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[447,696,695,770,87,53],"class_list":["post-1184","post","type-post","status-publish","format-standard","hentry","category-informatica","tag-c","tag-compiladores","tag-curiosidades","tag-informatica","tag-java","tag-programacion","entry"],"_links":{"self":[{"href":"https:\/\/www.tiendadeultramarinos.es\/index.php?rest_route=\/wp\/v2\/posts\/1184","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tiendadeultramarinos.es\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tiendadeultramarinos.es\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tiendadeultramarinos.es\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tiendadeultramarinos.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1184"}],"version-history":[{"count":14,"href":"https:\/\/www.tiendadeultramarinos.es\/index.php?rest_route=\/wp\/v2\/posts\/1184\/revisions"}],"predecessor-version":[{"id":1198,"href":"https:\/\/www.tiendadeultramarinos.es\/index.php?rest_route=\/wp\/v2\/posts\/1184\/revisions\/1198"}],"wp:attachment":[{"href":"https:\/\/www.tiendadeultramarinos.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1184"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tiendadeultramarinos.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1184"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tiendadeultramarinos.es\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1184"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}