Los operadores a nivel de bits se incorporaron al lenguaje C para facilitar el trabajo a bajo nivel con datos y hardware: configuración de registros, enmascaramiento, multiplicación y división por potencias de dos. Las reglas de su funcionamiento se establecieron en los tiempos de los procesadores de 8 y 16 bits.
A menudo se cometen errores al desplazar tipos signed, ya que el resultado depende de la implementación (desplazamiento aritmético o lógico), así como al exceder los límites del tamaño del tipo. Los errores pueden llevar a la corrupción de datos, cálculos incorrectos y comportamiento indefinido.
Desplazamiento a la izquierda (<<): equivale a multiplicar el valor por 2 elevado a la k (a << k). Siempre llena con ceros a la derecha.
Desplazamiento a la derecha (>>): para valores unsigned llena con ceros a la izquierda (desplazamiento lógico), y para signed puede llenar con el bit de signo (desplazamiento aritmético) o con ceros (el comportamiento depende del compilador).
Ejemplo:
unsigned int x = 5; // 0000 0101 unsigned int y = x << 1; // 0000 1010 == 10 int z = -4; // 1111 1100 (si 8 bits) int w = z >> 1; // Puede quedar 1111 1110 (-2) o 0111 1110 (depende de la implementación)
Características clave:
¿Qué sucederá al desplazar un número negativo a la derecha con >>?
El resultado depende de la implementación: más comúnmente es un desplazamiento aritmético que conserva el signo, ¡pero el estándar no lo garantiza!
¿Cuál es el resultado del desplazamiento por un número de bits mayor que la capacidad del tipo?
Comportamiento indefinido. Por ejemplo, 1 << 32 para un tipo de 32 bits puede dar cualquier cosa o incluso causar errores en el programa.
¿Se pueden usar operadores de bits para números de punto flotante?
No, los tipos estándar float, double no admiten operaciones de bits. Solo tipos enteros.
Un programador desplazó un int 32 para formar una máscara — en algunas plataformas esto resultó en cero, en otras en un valor indescifrable.
Pros:
Contras:
En su lugar, se usaron valores unsigned y enmascaramiento del número de bits mediante macros, con documentación clara y comprobación de la longitud del tipo a través de sizeof.
Pros:
Contras: