Acerca de¶
La manipulación de bits es una competencia esencial en C11 para la programación de bajo nivel,
el diseño de controladores de hardware, sistemas embebidos y algoritmos de compresión y criptografía.
Estos ejercicios ejercitan los operadores a nivel de bits (&, |, ^, ~, <<, >>),
el uso de enteros sin signo de ancho fijo (<stdint.h>) y el diseño de máscaras booleanas.
Capítulos de Apunte Correspondientes¶
Prerrequisitos Conceptuales¶
Antes de resolver esta guía, el estudiante debe dominar:
Representación binaria posicional y enteros sin signo de ancho fijo (
<stdint.h>).Operadores a nivel de bit en C11: AND (
&), OR (|), XOR (^), NOT (~), y desplazamientos (<<,>>).Construcción y aplicación de máscaras booleanas de bits (
(1U << n)).Precedencia de operadores en C y uso estricto de paréntesis defensivos.
Cuestiones de Estilo Aplicables¶
Tipos de ancho fijo: Utilizá tipos sin signo como
uint32_touint8_tde<stdint.h>para evitar comportamientos dependientes de signo o plataforma en desplazamientos a la derecha.Paréntesis explícitos: Dado que los operadores de bits tienen menor precedencia que los operadores relacionales y aritméticos, agrupá siempre las operaciones entre paréntesis (ej.
(n & (1U << pos)) != 0).Constantes sin signo: Empleá literales con sufijo
U(ej.1U << n) para evitar desbordamientos de enteros con signo.
Manipulación de Bits Individuales¶
Ejercicio 4.05.01 - Lectura del N-ésimo Bit ⭐⭐⭐⭐☆¶
Solution to Exercise 7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18#include <assert.h> #include <stdint.h> uint8_t obtener_bit(uint32_t valor, uint8_t n) { assert(n < 32); return (uint8_t)((valor >> n) & 1U); } int main(void) { assert(obtener_bit(5U, 0) == 1); assert(obtener_bit(5U, 1) == 0); assert(obtener_bit(5U, 2) == 1); assert(obtener_bit(0x80000000U, 31) == 1); assert(obtener_bit(0U, 15) == 0); return 0; }
Ejercicio 4.05.02 - Encendido del N-ésimo Bit (Set Bit) ⭐⭐⭐⭐☆¶
Solution to Exercise 8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17#include <assert.h> #include <stdint.h> uint32_t encender_bit(uint32_t valor, uint8_t n) { assert(n < 32); return valor | (1U << n); } int main(void) { assert(encender_bit(0U, 3) == 8U); assert(encender_bit(8U, 3) == 8U); assert(encender_bit(0U, 0) == 1U); assert(encender_bit(0U, 31) == 0x80000000U); return 0; }
Ejercicio 4.05.03 - Apagado del N-ésimo Bit (Clear Bit) ⭐⭐⭐⭐☆¶
Solution to Exercise 9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17#include <assert.h> #include <stdint.h> uint32_t apagar_bit(uint32_t valor, uint8_t n) { assert(n < 32); return valor & ~(1U << n); } int main(void) { assert(apagar_bit(15U, 1) == 13U); assert(apagar_bit(13U, 1) == 13U); assert(apagar_bit(1U, 0) == 0U); assert(apagar_bit(0xFFFFFFFFU, 31) == 0x7FFFFFFFU); return 0; }
Ejercicio 4.05.04 - Inversión del N-ésimo Bit (Toggle Bit) ⭐⭐⭐⭐☆¶
Solution to Exercise bits-4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16#include <assert.h> #include <stdint.h> uint32_t conmutar_bit(uint32_t valor, uint8_t n) { assert(n < 32); return valor ^ (1U << n); } int main(void) { assert(conmutar_bit(0U, 2) == 4U); assert(conmutar_bit(4U, 2) == 0U); assert(conmutar_bit(conmutar_bit(42U, 5), 5) == 42U); return 0; }
Algoritmos con Bits¶
Ejercicio 4.05.05 - Conteo de Bits Encendidos (Hamming Weight) ⭐⭐⭐⭐☆¶
Solution to Exercise bits-5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23#include <assert.h> #include <stdint.h> uint8_t contar_bits_encendidos(uint32_t n) { uint8_t cuenta = 0; while (n != 0) { n &= (n - 1U); cuenta++; } return cuenta; } int main(void) { assert(contar_bits_encendidos(7U) == 3); assert(contar_bits_encendidos(10U) == 2); assert(contar_bits_encendidos(0U) == 0); assert(contar_bits_encendidos(0xFFFFFFFFU) == 32); assert(contar_bits_encendidos(1U) == 1); return 0; }
Ejercicio 4.05.06 - Verificación de Potencia de Dos ⭐⭐☆☆☆¶
Solution to Exercise bits-6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19#include <assert.h> #include <stdbool.h> #include <stdint.h> bool es_potencia_de_dos(uint32_t n) { return (n > 0) && ((n & (n - 1U)) == 0); } int main(void) { assert(es_potencia_de_dos(16U) == true); assert(es_potencia_de_dos(18U) == false); assert(es_potencia_de_dos(1U) == true); assert(es_potencia_de_dos(0U) == false); assert(es_potencia_de_dos(0x80000000U) == true); assert(es_potencia_de_dos(0x7FFFFFFFU) == false); return 0; }
Ejercicio 4.05.07 - Intercambio de Variables sin Memoria Auxiliar (XOR Swap) ⭐⭐☆☆☆¶
Solution to Exercise bits-7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31#include <assert.h> #include <stddef.h> #include <stdint.h> void intercambiar_xor(uint32_t *a, uint32_t *b) { assert(a != NULL); assert(b != NULL); if (a != b) { *a = *a ^ *b; *b = *a ^ *b; *a = *a ^ *b; } } int main(void) { uint32_t x = 15U; uint32_t y = 99U; intercambiar_xor(&x, &y); assert(x == 99U && y == 15U); // Caso aliasing uint32_t mismo = 42U; intercambiar_xor(&mismo, &mismo); assert(mismo == 42U); return 0; }
Ejercicio 4.05.08 - Sistema de Permisos de Archivo con Máscaras de Bits ⭐⭐⭐⭐☆¶
Solution to Exercise bits-8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38#include <assert.h> #include <stdbool.h> #include <stdint.h> #define PERM_LECTURA (1U << 0) #define PERM_ESCRITURA (1U << 1) #define PERM_EJECUCION (1U << 2) uint8_t otorgar_permiso(uint8_t permisos, uint8_t mascara) { return permisos | mascara; } uint8_t revocar_permiso(uint8_t permisos, uint8_t mascara) { return permisos & ~mascara; } bool tiene_permiso(uint8_t permisos, uint8_t mascara) { return (permisos & mascara) == mascara; } int main(void) { uint8_t p = 0; p = otorgar_permiso(p, PERM_LECTURA | PERM_ESCRITURA); assert(tiene_permiso(p, PERM_LECTURA) == true); assert(tiene_permiso(p, PERM_ESCRITURA) == true); assert(tiene_permiso(p, PERM_EJECUCION) == false); p = revocar_permiso(p, PERM_ESCRITURA); assert(tiene_permiso(p, PERM_LECTURA) == true); assert(tiene_permiso(p, PERM_ESCRITURA) == false); return 0; }