“If you work with C or embedded systems, understanding bit flags is a must for writing memory-efficient code.”
Introduction
Bit flags are a technique used when dealing with multiple related boolean values.
When defining a boolean variable you actually reserve a dedicated byte (8-bits) in memory which is the smallest unit —which only requires 1 bit to represent true or false— you waste 7 bits per variable!
Example:
bool isBold = true;
bool isItalic = false;
bool isUnderlined = true;
// ...
Each of these variables has its own dedicated location in memory, which is a whole byte.
Bit flags solve this inefficiency: Instead of allocating an entire byte for a single boolean value, we can store up to eight distinct flags within a single byte! By using larger data types like long
(typically 32 or 64 bits), we can accommodate even more flags. The fundamental purpose of bit flags is therefore memory conservation.
This technique is particularly vital in memory-constrained systems—including operating systems, embedded devices, game engines, device drivers, and other performance-sensitive applications. It enables developers to efficiently pack multiple states or permissions, which is essential for low-level programming and high-performance scenarios.
Bitwise Operators
Bitwise operators perform operations directly on the binary representation of integers.
They allow you to manipulate bits individually in a very efficient way.
Common bitwise operators:
AND
&
OR
|
XOR
^
NOT
~
Left Shift
<<
Right Shift
>>
Logic operations:
Bit Flags Syntax
#include <stdint.h>
uint8_t styleFlags = 0; // Our 8-bit flag register
#define IS_BOLD 1 // 00000001
#define IS_ITALIC 2 // 00000010
#define IS_UNDERLINE 4 // 00000100
styleFlags
is our 8-bit flag register.
IS_BOLD
is bit 0 (decimal1
).IS_ITALIC
is bit 1 (decimal2
)IS_UNDERLINE
is bit 2 (decimal4
).
✅ The same flags can be defined using hexadecimal:
#define IS_BOLD 0x01 // 00000001
#define IS_ITALIC 0x02 // 00000010
#define IS_UNDERLINE 0x04 // 00000100
✅ Or using bit shifting:
#define IS_BOLD (1 << 0) // 00000001
#define IS_ITALIC (1 << 1) // 00000010
#define IS_UNDERLINE (1 << 2) // 00000100
Tip: This shifting method is more readable; you immediately know which bit represents each flag.
Bit Flags Operations
Add a flag
Set a bit ON using bitwise OR |
:
styleFlags |= IS_BOLD; // Enable BOLD
/*
styleFlags: 00000000
IS_BOLD: 00000001
OR
Result: 00000001 (BOLD is now ON)
*/
styleFlags |= IS_UNDERLINE; // Add UNDERLINE too
/*
styleFlags: 00000001
IS_UNDERLINE: 00000100
OR
Result: 00000101 (BOLD + UNDERLINE are ON)
*/
Remove a flag
Clear a bit OFF using bitwise AND &
with NOT ~
:
styleFlags &= ~IS_BOLD; // Disable BOLD
/*
styleFlags: 00000101
~IS_BOLD: 11111110
AND
Result: 00000100 (Only UNDERLINE is ON)
*/
Toggle a flag
Toggle means if it's ON ➜ make it OFF, and if it's OFF ➜ make it ON.
This is done using XOR ^
:
styleFlags ^= IS_ITALIC; // Toggle ITALIC
/*
styleFlags: 00000100
IS_ITALIC: 00000010
XOR
Result: 00000110 (UNDERLINE + ITALIC are ON)
*/
// Toggle again
styleFlags ^= IS_ITALIC;
/*
styleFlags: 00000110
IS_ITALIC: 00000010
XOR
Result: 00000100 (ITALIC turned OFF)
*/
Check a flag
Test if a bit is set using bitwise AND &
:
if (styleFlags & IS_BOLD) {
printf("Text is Bold!\n");
}
/*
styleFlags: 00000100
IS_BOLD: 00000001
AND
Result: FALSE (0) -> BOLD is OFF
*/
Conclusion
✅ Bit flags are a smart way to pack multiple on/off values into a single register, saving memory and giving you low-level control.
✅ Combine them with bitwise operators to set, clear, toggle, and check flags efficiently.
✅ This technique is widely used in embedded programming, operating systems, and anywhere performance and memory efficiency matter!
Try using bit flags in your next C project. Feel free to share your experience or ask questions below!
Top comments (1)
We can also use the binary notation
0b00000001
, but I agree that bitshift is much more convenient. I have been using bitshift in my code for a long time now when I need to store a lot of flags.