{"id":675,"date":"2010-12-31T02:20:29","date_gmt":"2010-12-31T01:20:29","guid":{"rendered":"http:\/\/blog.rastersoft.com\/?p=675"},"modified":"2010-12-31T02:20:29","modified_gmt":"2010-12-31T01:20:29","slug":"desplazando-bits","status":"publish","type":"post","link":"https:\/\/blog.rastersoft.com\/?p=675","title":{"rendered":"Desplazando bits"},"content":{"rendered":"<p>Hace mucho tiempo, cuando empec\u00e9 a programar en C, le\u00ed una curiosa advertencia sobre los operadores de desplazamiento de bits, los famosos &gt;&gt; y &lt;&lt;. Se afirmaba all\u00ed que, al desplazar una variable con ellos, los bits que sal\u00edan se perd\u00edan (l\u00f3gico, siendo un desplazamiento), pero que los bits que entraban por el lado opuesto ten\u00edan un valor indefinido, que pod\u00eda ser cero o uno seg\u00fan la implementaci\u00f3n.<\/p>\n<p>Es cierto que todos los programadores asumen que lo que entra es cero siempre; pero pese a todo, yo, que tiendo a ser demasiado cauto, opt\u00e9 por a\u00f1adir siempre una m\u00e1scara AND para poner a cero los bits entrantes y as\u00ed evitarme sorpresas.<\/p>\n<p>Sin embargo, hace unos d\u00edas, mientras optimizaba unas rutinas que hacen uso de desplazamientos, decid\u00ed investigar m\u00e1s a fondo el tema, porque a fin de cuentas una m\u00e1scara consume ciclos de reloj, as\u00ed que si hab\u00eda alguna forma de evitarla siempre ser\u00eda una mejora. Y lo que descubr\u00ed me dej\u00f3 gratamente sorprendido, porque en realidad el valor de los bits que entran no depende del compilador, sino que est\u00e1 perfectamente definido en el est\u00e1ndar.<\/p>\n<p>Cuando se utiliza el desplazamiento hacia la izquierda (&lt;&lt;), por el lado derecho siempre entran ceros. Ah\u00ed nunca hay problemas. Por otro lado, cuando se utiliza el desplazamiento hacia la derecha (&gt;&gt;) en una variable sin signo (por ejemplo, en un <strong>unsigned int<\/strong>), por la izquierda tambi\u00e9n entran siempre ceros.<\/p>\n<p>Sin embargo, cuando utilizamos variables con signo (por ejemplo,<strong> short int<\/strong>) en un desplazamiento hacia la derecha, los bits que entren por la izquierda ser\u00e1n una copia del bit de mayor peso del valor original. As\u00ed, si ten\u00edamos un n\u00famero negativo (su bit de mayor peso est\u00e1 a uno), al desplazarlo hacia la derecha seguir\u00e1 siendo negativo, porque los bits entrantes ser\u00e1n unos; en cambio, si era un n\u00famero positivo (su bit de mayor peso est\u00e1 a cero) los bits entrantes ser\u00e1n cero.<\/p>\n<p>Supongo que la raz\u00f3n de hacerlo as\u00ed es que, si se utilizan rotaciones para hacer divisiones, se conserva el signo.<\/p>\n<p>Este c\u00f3digo ilustra perfectamente lo dicho aqu\u00ed:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">#include &lt;stdio.h&gt;\n\nvoid desplaza(unsigned int o) {\n\n  signed int s1,s2;\n  unsigned int u1,u2;\n\n  s1=s2=u1=u2=o; \/\/ asignamos el mismo valor a las cuatro variables\n\n  s1&gt;&gt;=4; \/\/ desplazamos cuatro veces cada una de ellas\n  s2&lt;&lt;=4;\n  u1&gt;&gt;=4;\n  u2&lt;&lt;=4;\n\n  printf(\"Con signo:ntdesplazamiento a la derecha\u00a0\u00a0 %08Xn\",s1);\n  printf(\"tdesplazamiento a la izquierda %08Xn\",s2);\n  printf(\"Sin signo:ntdesplazamiento a la derecha\u00a0\u00a0 %08Xn\",u1);\n  printf(\"tdesplazamiento a la izquierda %08Xnn\",u2);\n}\n\nint main() {\n\n  printf(\"nDesplazamiento de 4 posiciones.n\");\n  printf(\"Valor original: 0xA50000A5 (bit de mayor peso a uno).n\");\n  desplaza(0xA50000A5);\n  printf(\"nValor original: 0x5A00005A (bit de mayor peso a cero).n\");\n  desplaza(0x5A00005A);\n\n  return 0;\n}<\/pre>\n<\/div>\n<p>La salida es la siguiente, donde se aprecia claramente como el bit superior se replica en los desplazamientos a la derecha de las variables con signo, pero no en el resto de los casos:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">Desplazamiento de 4 posiciones.\nValor original: 0xA50000A5 (bit de mayor peso a uno).\nCon signo:\n  desplazamiento a la derecha\u00a0\u00a0 FA50000A\n  desplazamiento a la izquierda 50000A50\nSin signo:\n  desplazamiento a la derecha\u00a0\u00a0 0A50000A\n  desplazamiento a la izquierda 50000A50\n\nValor original: 0x5A00005A (bit de mayor peso a cero).\nCon signo:\n  desplazamiento a la derecha\u00a0\u00a0 05A00005\n  desplazamiento a la izquierda A00005A0\nSin signo:\n  desplazamiento a la derecha\u00a0\u00a0 05A00005\n  desplazamiento a la izquierda A00005A0<\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Hace mucho tiempo, cuando empec\u00e9 a programar en C, le\u00ed una curiosa advertencia sobre los operadores de desplazamiento de bits, los famosos &gt;&gt; y &lt;&lt;. Se afirmaba all\u00ed que, al desplazar una variable con ellos, los bits que sal\u00edan se perd\u00edan (l\u00f3gico, siendo un desplazamiento), pero que los bits que entraban por el lado opuesto &hellip; <a href=\"https:\/\/blog.rastersoft.com\/?p=675\" class=\"more-link\">Seguir leyendo <span class=\"screen-reader-text\">Desplazando bits<\/span> <span class=\"meta-nav\">&rarr;<\/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,6,7],"tags":[],"class_list":["post-675","post","type-post","status-publish","format-standard","hentry","category-programacion","category-trucos","category-tutoriales"],"_links":{"self":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/675","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=675"}],"version-history":[{"count":0,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/675\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=675"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=675"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=675"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}