Repetimos el juego del post anterior: que levante la mano quien ha escrito recientemente código que utiliza las operaciones bit a bit. O bien, levante la mano, sin antes ir a volver a leer un manual de C, aquellos de vosotros que saben cómo usar y/o describir perfectamente las operaciones bit a bit. Uhmm ... Veo pocas manos levantadas. El hecho es que las bitwise opeartions son una de las partes del C menos conocida, de uso dudoso y poco frecuente, en definitiva, una de las partes que, por falta de práctica, se olvida (y he usado exactamente las mismas palabras del post anterior: soy ecologista, cuando puedo reciclo).
En comparación con las union, por otra parte, hay que decir que sobre las operaciones bit a bit el fantástico K&R no es particularmente claro y detallado, y las trata (como son) como un tema secundario, y no te involucra con decenas de ejemplos entretenidos que te ayudan en memorizar perfectamente el argumento, de hecho, que yo recuerde de la última vez que lo leí, hay solo un par de páginas que te se escapaban de las manos y que ya has olvidado cuando pasas al siguiente capítulo. Bueno, la biblia K&R (que considero sagrada) tiene algunos puntos no tan atractivos.
Refrescamos: los operadores de bitwise (que operan en los bits individuales) son:
Ahora bien, sin entrar en discursos aburridos, nos dirigimos a una pequeña tabla y a algunos ejemplos sencillos."&" AND "|" OR "^" XOR "~" NOT (complemento a 1) "<<" SHIFT hacia la izquierda ">>" SHIFT hacia la derecha NOTA: - el NOT es un operador unario: funciona con un solo argumento indicado a la derecha. - los operadores de shift son operadores unarios: operan con un solo argumento indicado a la izquierda.
Aquí está la tabla:
Y aquí están los simples ejemplos prácticos:"& ": el resultado es 1 si los dos operandos son 1. En caso contrario 0. "|" : el resultado es 0 si los dos operandos son 0. En caso contrario 1. "^ ": el resultado es 1 si los dos operandos son diferentes. En caso contrario 0. "~ ": el resultado es 1 si el operando es 0. En caso contrario 0. "<<n": el resultado es el operando con todos los bits desplazados a la izquierda por n posiciones. ">>n": el resultado es el operando con todos los bits desplazados a la derecha por n posiciones.
Tener en cuenta que en las operaciones de shift los bits nuevos que entran por la derecha (en el shift hacia la izquierda) valen 0, y los bit nuevos que entran por la izquierda (en el shift hacia la derecha) valen 0.AND int a = 74; // 0 1 0 0 1 0 1 0 int b = 174; // 1 0 1 0 1 1 1 0 int c = a & b; // 0 0 0 0 1 0 1 0 resultado c=10 OR int a = 74; // 0 1 0 0 1 0 1 0 int b = 174; // 1 0 1 0 1 1 1 0 int c = a | b; // 1 1 1 0 1 1 1 0 resultado c=238 XOR int a = 74; // 0 1 0 0 1 0 1 0 int b = 174; // 1 0 1 0 1 1 1 0 int c = a & b; // 1 1 1 0 0 1 0 0 resultado c=228 NOT int a = 74; // 0 1 0 0 1 0 1 0 int b = ~b; // 1 0 1 1 0 1 0 1 resultado c=181 SHIFT hacia la izquierda int a = 74; // 0 1 0 0 1 0 1 0 int b = a<<2; // 0 0 1 0 1 0 0 0 resultado c=296 SHIFT hacia la derecha int a = 74; // 0 1 0 0 1 0 1 0 int b = a>>2; // 0 0 0 1 0 0 1 0 resultado c=18
Tener en cuenta también que el shift hacia la derecha es equivalente a una división por múltiplos de 2 (>>1 es una división por 2, >>2 es una división por 4, etc.) , Mientras que el shift hacia la izquierda es equivalente a una multiplicación por múltiplos de 2 (<<1 es una multiplicación por 2, <<2 es una multiplicación por 4, etc.). Estas operaciones de multiplicación y división son muy rápidas, y se puede tener la tentación de utilizarlas para acelerar el código: bueno, antes de hacerlo, leer de nuevo (o leer) esto.
Y me gustaría añadir una advertencia: en función del tamaño del tipo del operando, y la presencia o ausencia del bit de signo, las multiplicaciones y divisiones con shift pueden dar resultados inesperados. Hablaremos de esto en el próxima episodio, donde vamos a hacer unos cuantos ejemplos prácticos de código que utiliza las bitwise operations (y no contengáis la respiración, mientras tanto...).
Hasta el próximo post.