Manipulación de bits

C dispone de operadores booleanos que permiten transformar los bits que componen un valor numérico. En este vídeo te explico como usar los operadores NOT, AND, OR y XOR para manipular los bits de un número.

Desde hace mucho tiempo, los humanos hemos adoptado el sistema de numeración en base 10, que utiliza cifras del 0 al 9 para representar números. Cada cifra tiene una posición que determina su valor, como las unidades, decenas, centenas, y así sucesivamente. Sin embargo, cuando programamos, aunque escribamos un número decimal como 45, internamente el ordenador no lo almacena así. Los ordenadores trabajan en base 2, es decir, en sistema binario, que solo usa dos cifras: 0 y 1.

Esto significa que un número como 45 se representa en memoria como una secuencia de bits, por ejemplo, 00101101. Normalmente, la memoria se organiza en celdas de 8 bits, lo que permite representar 256 valores diferentes. Pero hay memorias con tamaños distintos, como 16 o 32 bits, y por eso es importante elegir bien el tipo de dato en C, ya que cada tipo define cuántos bits se usan para almacenar un número y, por tanto, el rango de valores que puede contener.

En C contamos con operadores binarios que nos permiten manipular directamente estos bits. Los principales son NOT, AND, OR y XOR. Para entenderlos, partimos de un número binario, por ejemplo, 10011100, que en decimal es 156. Cada bit tiene una posición, desde la 7 (bit más significativo o MSB) hasta la 0 (bit menos significativo o LSB).

El operador NOT es un operador unario que invierte cada bit del número: donde había un 1 pone un 0, y donde había un 0 pone un 1. Por ejemplo, el NOT de 10011100 es 01100011, que equivale a 99 en decimal. En C, se usa la tilde ~ para aplicar este operador. Si declaramos una variable foo como un signed char con valor 156 y aplicamos ~foo, el resultado puede parecer extraño, como -157, debido a cómo se interpreta el tipo y el tamaño de la variable. Esto se debe a que el operador NOT trabaja con enteros de tamaño predeterminado (normalmente 32 bits), y para obtener el resultado esperado debemos hacer un cast explícito a signed char para limitar la operación a 8 bits.

signed char foo = 156;
printf("%d\n", foo);          // Imprime 156
printf("%d\n", (signed char)~foo);  // Imprime 99

Los operadores AND, OR y XOR trabajan con dos números binarios. Por ejemplo, tomemos A = 10111001 (185 decimal) y B = 00111001 (52 decimal).

El operador AND (& en C) produce un bit 1 solo si ambos bits correspondientes en A y B son 1. En nuestro ejemplo, A & B da como resultado un número con solo dos bits en 1, que es 48 en decimal.

El operador OR (| en C) produce un bit 1 si al menos uno de los bits correspondientes en A o B es 1. Así, A | B da 189 en decimal.

El operador XOR (^ en C) produce un bit 1 solo si exactamente uno de los bits correspondientes es 1, pero no ambos. En nuestro caso, A ^ B da 141 en decimal.

unsigned char A = 185; // 10111001
unsigned char B = 52;  // 00111001

printf("%d\n", A & B);  // Imprime 48
printf("%d\n", A | B);  // Imprime 189
printf("%d\n", A ^ B);  // Imprime 141

Estos operadores son fundamentales para manipular bits y se usan para crear máscaras de bits, que permiten activar, desactivar o consultar bits específicos dentro de un número. Además, combinados con operadores de desplazamiento, ofrecen herramientas muy potentes para optimizar y controlar datos a nivel binario en C y otros lenguajes.

Es importante familiarizarse con la representación binaria y la lógica detrás de estos operadores para aprovechar al máximo su potencial en programación. Así, podremos realizar operaciones eficientes y precisas que van más allá de la simple aritmética decimal.

Lista de reproducción
  1. 1
    Instalar CodeBlocks
    15 minutos
  2. 2
    Funciones y hola mundo
    17 minutos
  3. 3
    Variables y tipos de datos
    17 minutos
  4. 4
    Condicionales y operadores lógicos
    16 minutos
  5. 5
    Bucles
    11 minutos
  6. 6
    Punteros
    12 minutos
  7. 7
    Arrays
    14 minutos
  8. 8
    Estructuras
    12 minutos
  9. 9
    Otras construcciones de C
    9 minutos
  10. 10
    Memoria dinámica
    8 minutos
  11. 11
    El preprocesador (parte 1)
    10 minutos
  12. 12
    El preprocesador (parte 2)
    9 minutos
  13. 13
    Archivos de cabecera y múltiples .c (parte 1)
    8 minutos
  14. 14
    Archivos de cabecera y múltiples .c (parte 2)
    9 minutos
  15. 15
    C desde la línea de comandos (parte 1)
    8 minutos
  16. 16
    C desde la línea de comandos (parte 2)
    9 minutos
  17. 17
    Break y continue
    10 minutos
  18. 18
    Goto
    13 minutos
  19. 19
    Manipulación de bits
    15 minutos
  20. 20
    Máscaras de bit
    19 minutos
  21. 21
    Archivos (1): fopen y fclose
    13 minutos
  22. 22
    Archivos (2): leer con fgetc
    9 minutos
  23. 23
    Archivos (3): fseek y ftell
    11 minutos
  24. 24
    Archivos (4): leer con fgets
    9 minutos
  25. 25
    Archivos (5): fputc y fputs
    7 minutos
  26. 26
    Archivos (6): volcar en archivos con fwrite
    10 minutos
  27. 27
    Archivos (7): fread, fwrite y los arrays
    10 minutos
  28. 28
    Archivos (8): entrada estándar y salida estándar
    9 minutos
  29. 29
    Archivos (9): buffers
    14 minutos
  30. 30
    Archivos (y 10): otras funciones útiles con archivos
    5 minutos
  31. 31
    printf (1)
    18 minutos
  32. 32
    printf (parte 2)
    12 minutos
  33. 33
    scanf (parte 1)
    17 minutos
  34. 34
    scanf (parte 2)
    17 minutos
  35. 35
    fprintf, sprintf y snprintf
    8 minutos
  36. 36
    Tipos de datos opacos
    13 minutos
  37. 37
    Bibliotecas estáticas
    13 minutos
  38. 38
    Bibliotecas dinámicas
    15 minutos
  39. 39
    Más flags: i mayúscula (include), wall, werror, pedantic...
    12 minutos
  40. 40
    pkg-config
    12 minutos
  41. 41
    Make
    17 minutos
  42. 42
    GDB
    21 minutos
  43. 43
    Variables globales
    6 minutos
  44. 44
    extern
    9 minutos
  45. 45
    Funciones variádicas
    12 minutos
  46. 46
    El optimizador de GCC y la opción -O
    12 minutos
  47. 47
    Volatile
    6 minutos