# Bitwise Operators and Bit Flags

An introduction to the bitwise AND, OR, and XOR operators - and one of their most interesting use cases
###### Ryan McCombe
Published

Behind the scenes, every variable and object we create when programming is stored in binary. That is, a series of binary digits (bits) that can have only two possible vales: on or of - typically represented by 1 or 0

Generally, we donâ€™t need to work on this level. Our compilers and interpreters just abstract this away so weâ€™re acting on higher level objects, like numbers andÂ strings.

But, there are some use cases where working at the binary level is the best option. Additionally, there are some operators that help us doÂ that.

Then, we will introduce and implement one of the the main scenarios where weâ€™d want to use them: bitÂ flags.

## Logical Operators vs Bitwise Operators

We previously saw how the || and && operators can be used to combine booleans in differentÂ ways.

These are called the â€ślogical ORâ€ť and â€ślogical ANDâ€ť operators. They have their bitwiseÂ counterparts:

• the bitwise OR operator - C++ and many other programming languages represent this by a single |
• the bitwise XOR (exclusive or) operator - typically represented by a caret: ^
• the bitwise AND - typically represented by a single &

## The Bitwise OR Operator: |

The bitwise OR operator looks at the binary representation of its two operands and returns a new object of the same type. Every bit in this new object is set to 1 if either of the operands had a 1 in that sameÂ position.

Itâ€™s easier to demonstrate with anÂ example:

## The Bitwise XOR (exclusive or) Operator: ^

XOR works very similarly to OR. The only difference is that, when both operands had a 1 in the same position, the result of XOR will have a 0 in that correspondingÂ position.

Another way to think of XOR is that it will have 1 in each position where the operands had differentÂ values.

Hereâ€™s anÂ example:

## The Bitwise AND Operator: &

Similarly, the bitwise AND operator looks at the binary representation of its two operands and returns a new object of the same type. Every bit in this new object is set to 1 if both of the operands had a 1 in that sameÂ position.

Hereâ€™s anÂ example:

## Use Case: Bit Flags

Imagine we had a function that creates a window. That function additionally had a collection of settings (or â€śflagsâ€ť) for how that window would work. For example, is it resizable? Is it movable? Is it fullÂ screen?

Without bitwise operators, there would be two main ways we would create this. We could just have all those booleans be arguments to theÂ function:

CreateWindow("Test Window", false, true, true, false, true);


This is not especially readable. What flags are we setting to be true here? Thatâ€™s not clear, especially when we donâ€™t have IDE tooltips to helpÂ us.

Alternatively, our function could accept a structÂ instead:

WindowSettings Settings;
Settings.AlwaysOnTop = true;
Settings.Movable = true;
Settings.Closable = true;
CreateWindow("Test Window", Settings);


This makes it clearer what flags weâ€™re setting, but is quite verbose, and may have a performanceÂ overhead.

The best approach for this is commonly to use â€śbit flagsâ€ť, and bitwise operators can help us implementÂ them.

## Using Bitwise Operators for Bit Flags in C++

With bitwise operators, we can make our API muchÂ cleaner:

CreateWindow("Test Window", ALWAYS_ON_TOP | MOVABLE | CLOSABLE);


There are many ways to make this work. The standard library comes with a bitset class to solve this problem. Many others use an elaborate solution that involves enums. Here, weâ€™ll do a basic, raw implementation, so we can fully understand what is going on at a binaryÂ level.

The first step is to chose a numeric type for our flags. We want our type to have enough bits to cover every possibleÂ flag.

Here, we have 5 flags, so an 8 bit unsigned integer like uint8_t will work. This can support 8 bits, but we will only need 5. The first 3 bits will always be 0 in this setup, so weâ€™ll ignore them for clarity in ourÂ explanation.

Next, we need to choose a number for each of our flags. We want our numbers to be chosen such that each one has a single bit set to 1, and it is a different bit for each number. ForÂ example:

// We include NONE just so we have a descriptive way
// to represent the absence of any flags
static const uint8_t NONE { 0 }; // 00000

// Flags
static const uint8_t RESIZABLE { 1 }; // 00001
static const uint8_t MOVABLE { 2 }; // 00010
static const uint8_t CLOSABLE { 4 }; // 00100
static const uint8_t FULLSCREEN { 8 }; // 01000
static const uint8_t ALWAYS_ON_TOP { 16 }; // 10000


This doubling pattern can continue if we need more flags. If we need more than 8 flags, weâ€™d need to upgrade our type to, for example, a uint16_t

We can now combine our flags in any way we want using the bitwise OR operator. Each possible combination will generate a distinct pattern of bits. In total, there are 32 possibilities, from 0 toÂ 31:

// 00001 | 00010 = 00011 = 3
RESIZABLE | MOVABLE

// 00001 | 00100 = 00101 = 5
RESIZABLE | CLOSABLE

// 10000 | 00001 = 10001 = 17
ALWAYS_ON_TOP | RESIZABLE

// 00010 | 00100 | 01000 = 01110 = 14
MOVABLE | CLOSABLE | FULLSCREEN

// 10001 | 01000 | 00100 | 00010 | 00001 = 11111 = 31
RESIZABLE | MOVABLE | CLOSABLE | FULLSCREEN | ALWAYS_ON_TOP


## Checking if a Bit Flag was set in C++

We can now change which flags were set using the bitwise & operator. For example, to check if the CLOSABLE flag was set, we can doÂ this:

void CreateWindow(string Title, uint8_t flags = NONE) {
if(flags & CLOSABLE) {
cout << "CLOSABLE was set" << endl;
}
}


Itâ€™s likely to be unclear why this works, but itâ€™s important to understand theÂ logic.

Each of our possible flags will only have one bit containing a 1. In the case of CLOSABLE, it is in the 3rd position: 00100

Therefore, given how the bitwise & works, there are only two possible outcomes when one of the operands is 00100: it will either return 00100 or 00000

It will result in 00100 if the other operand also had a 1 in the 3rd position, ie, it also had CLOSABLE enabled. 00100 is equivalent to the decimal number 4, which is truthy, so the if statementÂ passes.

If the incoming argument did not have a 1 in that position, the CLOSABLE flag was not included. Therefore, flags & CLOSABLE will result in the binary output 00000, which is equivalent to the decimal number 0, which isÂ falsy.

## Full Example of C++ Bit Flags using Bitwise Operators

The full code for this example is availableÂ below:

#include <iostream>
using std::cout, std::string;

static const uint8_t NONE { 0 }; // 00000
static const uint8_t RESIZABLE { 1 }; // 00001
static const uint8_t MOVABLE { 2 }; // 00010
static const uint8_t CLOSABLE { 4 }; // 00100
static const uint8_t FULLSCREEN { 8 }; // 01000
static const uint8_t ALWAYS_ON_TOP { 16 }; // 10000

void CreateWindow(string Title, uint8_t flags = NONE) {
cout << Title << " has these flags:";
if (flags == NONE) {
cout << " NONE";
return;
}
if (flags & RESIZABLE) {
cout << " RESIZABLE";
}
if (flags & MOVABLE) {
cout << " MOVABLE";
}
if (flags & CLOSABLE) {
cout << " CLOSABLE";
}
if (flags & FULLSCREEN) {
cout << " FULLSCREEN";
}
if (flags & ALWAYS_ON_TOP) {
cout << " ALWAYS_ON_TOP";
}
}

int main() {
CreateWindow("Test Window", MOVABLE | CLOSABLE);
}


This program yields the followingÂ output:

Test Window has these flags: MOVABLE CLOSABLE


## Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, unlimited access!

### This course includes:

• 66 Lessons
• Over 200 Quiz Questions
• Capstone Project
• Regularly Updated
• Help and FAQ