Lesson 14 · 14 of 20
Bitwise operators and flags · C
Store several permissions in one integer with bit flags in C: set with |, clear with & and ~, toggle with ^ and test with &.

A flag is a bit with its own meaning. The enum gives each permission a different bit using shifts: 1 << 0 is 1, 1 << 1 is 2, 1 << 2 is 4 and 1 << 3 is 8. A single unsigned then holds all four permissions at once, which is how file permissions and the options of many APIs work.
`|` (OR) combines bits: READ | WRITE is 0011. |= adds a permission without touching the others. `&` with `~` removes one: ~WRITE has every bit set except the write bit, and ana &= ~WRITE turns it off. `^` (XOR) flips it: it turns ADMIN on the first time and would turn it off the second.
To test a permission, use &: guest & WRITE is 0 when the bit is off. ana & guest gives the bits both have, here only READ, which is 1.
show prints the bits from high to low with perms >> bit & 1: it shifts right until the wanted bit is last and keeps only that one. >> binds tighter than &, but when in doubt, add parentheses.
The last loop counts the bits set with a classic trick: v &= v - 1 clears the lowest 1, so the loop runs once per permission. Always use unsigned types for bit work: shifting negative numbers is not well defined.
Code · 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;}Output · 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
Key points
x |= Fsets,x &= ~Fclears,x ^= Ftoggles.x & Ftests whether the bit is set.1 << nis bitn;x >> nshifts right.- Use
unsignedtypes for bits.
Exercise
Add a SHARE = 1 << 4 flag, make show print five bits and write int has_all(unsigned perms, unsigned wanted) that says whether every permission in wanted is present.