Lección 14 · 14 de 20
Operadores de bits y banderas · C
Guarde varios permisos en un solo entero con banderas de bits en C: activar con |, quitar con & y ~, alternar con ^ y comprobar con &.

Una bandera es un bit con significado propio. El enum da a cada permiso un bit distinto con desplazamientos: 1 << 0 es 1, 1 << 1 es 2, 1 << 2 es 4 y 1 << 3 es 8. Así un solo unsigned guarda los cuatro permisos a la vez, que es como lo hacen los permisos de archivos o las opciones de muchas API.
`|` (O) junta bits: READ | WRITE es 0011. Con |= se añade un permiso sin tocar los demás. `&` con `~` quita uno: ~WRITE tiene todos los bits a 1 menos el de escribir, y ana &= ~WRITE lo apaga. `^` (O exclusivo) lo invierte: activa ADMIN la primera vez y lo desactivaría la segunda.
Para comprobar un permiso se usa &: guest & WRITE es 0 si el bit está apagado. ana & guest da los bits que tienen los dos, aquí solo READ, que vale 1.
show escribe los bits de mayor a menor con perms >> bit & 1: desplaza a la derecha hasta dejar el bit buscado en la última posición y se queda solo con él. >> tiene más prioridad que &, pero ante la duda conviene poner paréntesis.
El último bucle cuenta los bits a 1 con un truco clásico: v &= v - 1 apaga el 1 más bajo, así que el bucle da tantas vueltas como permisos hay. Use siempre tipos unsigned para trabajar con bits: desplazar números negativos no está bien definido.
Código · main.c
#include <stdio.h>// One bit per permission: 1, 2, 4, 8...enum { READ = 1 << 0, WRITE = 1 << 1, DELETE = 1 << 2, ADMIN = 1 << 3 };void show(const char *who, unsigned perms) { printf("%-6s ", who); for (int bit = 3; bit >= 0; bit--) putchar(perms >> bit & 1 ? '1' : '0'); // binary printf(" %s%s%s%s\n", perms & READ ? " read" : "", perms & WRITE ? " write" : "", perms & DELETE ? " delete" : "", perms & ADMIN ? " admin" : "");}int main(void) { unsigned ana = READ | WRITE; // | turns bits on show("Ana", ana); ana |= DELETE; // add one permission show("Ana", ana); ana &= ~WRITE; // & with ~ turns one bit off show("Ana", ana); ana ^= ADMIN; // ^ toggles: on now, off if repeated show("Ana", ana); unsigned guest = READ; printf("Guest can write? %s\n", (guest & WRITE) ? "yes" : "no"); printf("Common to both: %u\n", ana & guest); int bits = 0; for (unsigned v = ana; v; v &= v - 1) bits++; // clears the lowest 1 each time printf("Ana has %d permissions; 5 << 2 = %d, 40 >> 3 = %d\n", bits, 5 << 2, 40 >> 3); return 0;}Salida · cc main.c -o main && ./main
Ana 0011 read write Ana 0111 read write delete Ana 0101 read delete Ana 1101 read delete admin Guest can write? no Common to both: 1 Ana has 3 permissions; 5 << 2 = 20, 40 >> 3 = 5
Para recordar
x |= Factiva,x &= ~Fdesactiva,x ^= Falterna.x & Fcomprueba si el bit está activo.1 << nes el bitn;x >> ndesplaza a la derecha.- Para bits, use tipos
unsigned.
Ejercicio
Añada la bandera SHARE = 1 << 4, cambie show para que escriba cinco bits y escriba una función int has_all(unsigned perms, unsigned wanted) que diga si están todos los permisos de wanted.