Skip to content

Expert · Bits, undefined behaviour and safety · topic 42 of 60 · 25 min

Masks and flags

Explanation

A mask selects certain bits. The four basic operations on bit n of x are: set (x |= 1u << n), clear (x &= ~(1u << n)), toggle (x ^= 1u << n) and test (x & (1u << n)). Flags pack many yes/no options into one integer, as Linux file permissions do (0755). Masks and shifts also extract fields from packed values such as hardware register readings.

The four operations

c
unsigned x = 0;          /* 0000 0000 */
x |= 1u << 3;            /* set bit 3:    0000 1000 */
x |= 1u << 0;            /* set bit 0:    0000 1001 */
x ^= 1u << 7;            /* toggle bit 7: 1000 1001 */
x &= ~(1u << 3);         /* clear bit 3:  1000 0001 */
if (x & (1u << 7)) puts("bit 7 is on");
GoalCodeWhy it works
Set bit nx |= 1u << nOR with 1 forces a 1; OR with 0 changes nothing
Clear bit nx &= ~(1u << n)AND with 0 forces a 0; AND with 1 changes nothing
Toggle bit nx ^= 1u << nXOR with 1 flips; XOR with 0 keeps
Test bit n(x >> n) & 1u, or x & (1u << n)Isolates that bit

Named flags

c
enum {
    PERM_READ  = 1u << 0,   /* 0001 */
    PERM_WRITE = 1u << 1,   /* 0010 */
    PERM_ADMIN = 1u << 2,   /* 0100 */
};

unsigned perms = PERM_READ | PERM_WRITE;          /* combine flags with | */
if (perms & PERM_WRITE) puts("can write");
perms &= ~PERM_WRITE;                             /* revoke write */
int is_admin = (perms & PERM_ADMIN) != 0;

Many system APIs work like this: fopen-style flags in open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644) on Linux, socket options, and graphics settings. One integer carries many independent options.

Linux permissions as bits

output
0755 (octal) = 111 101 101 (binary)
owner: rwx   group: r-x   others: r-x
r = 4, w = 2, x = 1 in each group of three bits
chmod 644 file → owner rw-, group r--, others r--.

Extracting and inserting fields

c
/* A 16-bit sensor register: bits 15..12 = channel, bits 11..0 = reading */
uint16_t reg = 0x3A7F;
unsigned channel = (reg >> 12) & 0xFu;      /* 0x3 */
unsigned reading = reg & 0x0FFFu;           /* 0xA7F = 2687 */

/* write a new channel (5) without touching the reading */
reg = (uint16_t)((reg & ~0xF000u) | ((5u & 0xFu) << 12));   /* 0x5A7F */
Careful: When changing one field of a hardware register, always read-modify-write with a mask (clear the field, then OR in the new value). Writing the whole register with a new value can switch off other features that share it. In embedded code, also check whether the register must be accessed through a volatile pointer (module 12).
Think of it like this: Flags in one integer are like the tick boxes on a hotel booking form ("breakfast", "airport pickup", "late checkout"): one form, many independent yes/no answers. Setting a flag ticks a box, clearing it erases the tick, and testing reads it.
Tip: Define masks with names (PERM_WRITE, CH_MASK = 0xF000u, CH_SHIFT = 12) rather than writing magic numbers inline. Bit code is hard enough to read without guessing what 0x1000 means.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Masks and flags · 1/6

Masks and flags

In this lesson you will use masks to set, clear, toggle and test bits.

Prefer a video by a teacher? Find free videos on “c bit masking set clear toggle bit flags embedded” on YouTube ↗

In real life: Feature flags in a set-top box

A set-top box stores its enabled features in one 32-bit settings word saved in flash memory: HD, subtitles, parental lock, auto-update and so on. The menu code sets, clears and tests individual bits, and the whole word is saved in a single write.

c
enum { F_HD = 1u << 0, F_SUBTITLES = 1u << 1, F_PARENTAL = 1u << 2, F_AUTOUPDATE = 1u << 3 };
uint32_t settings = F_HD | F_AUTOUPDATE;
settings |= F_PARENTAL;                 /* parent turns on the lock */
settings &= ~F_AUTOUPDATE;              /* user disables auto-update */
printf("parental: %s\n", (settings & F_PARENTAL) ? "on" : "off");

Practice (0/3 done)

Task 1 · Question

unsigned x = 0x0F; x &= ~(1u << 2); What is x?

Task 2 · Code · Javascript

The same mask logic in JavaScript, which runs here: permissions use READ = 1, WRITE = 2, ADMIN = 4. Write grant(perms, flag), revoke(perms, flag) and has(perms, flag), using | , & and ~.

Task 3 · Practice

A 16-bit status register has: bit 0 = power on, bit 1 = error, bits 4–7 = mode (0–15), bits 8–15 = temperature in °C. In C, write functions to test power, set and clear the error bit, read the mode, write a new mode without changing other bits, and read the temperature. Test them with printf of the register in hex.

Quick quiz

Question 1

1.Which expression clears bit 5 of x?

Question 2

2.chmod 640 gives others which permissions?

Question 3

3.How do you combine two flags A and B?

Question 4

4.What does (reg >> 8) & 0xFF extract?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which expression clears bit 5 of x?

Answer: x &= ~(1u << 5)

AND with a mask that has a 0 only at bit 5.

chmod 640 gives others which permissions?

Answer: none

The last digit 0 means no permissions for others.

How do you combine two flags A and B?

Answer: A | B

OR sets both bits.

What does (reg >> 8) & 0xFF extract?

Answer: Bits 8–15 (the high byte of a 16-bit value)

Shift the field down, then mask it.

A file has permission 6 for its owner. What may the owner do?Related

Answer: Read and write

6 = 110: read (4) and write (2), no execute (1).

From Bits: AND, OR, XOR and shifts

What is the dotted decimal mask for /27?Related

Answer: 255.255.255.224

/27 = 24 + 3: three ones in the last octet = 128 + 64 + 32 = 224.

From Subnet masks, prefix length and wildcard masks

What is 1u << 10?Related

Answer: 1024

2^10.

From Bitwise operators

Which file holds Linux password hashes?Related

Answer: /etc/shadow

/etc/shadow holds the hashes and is readable only by root (and the shadow group).

From Linux security basics

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “Bits, undefined behaviour and safety” before its exam: Undefined behaviour, Secure and defensive C, Function pointers and callbacks.
  2. Module 9 exam: Bits, undefined behaviour and safety · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Data structures in C. 60 topics left in the course before the final exam.

← Previous: Bitwise operators