# Safe Bitfields in C++

DevFeed: [Safe Bitfields in C++](<https://devfeed.tech/articles/safe-bitfields-in-c-21002.md>)

Original publisher: [Read original article](<https://preshing.com/20150324/safe-bitfields-in-cpp>)

Author: Jeff Preshing

Published: 2015-03-24T10:15:00Z

Content type: article

Language: en

Sources: [Jeff Preshing](<https://devfeed.tech/sources/jeff-preshing.md>)

Topics: [C++](<https://devfeed.tech/topics/c-plus-plus.md>), [Programming](<https://devfeed.tech/topics/programming.md>), [Development](<https://devfeed.tech/topics/development.md>), [debug](<https://devfeed.tech/topics/debug.md>)

Tags: [arrays](<https://devfeed.tech/tags/arrays.md>), [atomic](<https://devfeed.tech/tags/atomic.md>), [c-plus-plus](<https://devfeed.tech/tags/c-plus-plus.md>), [debug](<https://devfeed.tech/tags/debug.md>), [github](<https://devfeed.tech/tags/github.md>)

## AI overview

This article explains a C++ technique for defining safe bitfields with preprocessor macros and templates. The bitfields pack values into an unsigned integer, support packed arrays and atomic operations, and use runtime assertions to detect overflow, underflow, and values that exceed member limits.

## Source excerpt

In my cpp11-on-multicore project on GitHub, there's a class that packs three 10-bit values into a 32-bit integer. I could have implemented it using traditional bitfields... struct Status { uint32_t readers : 10; uint32_t waitToRead : 10; uint32_t writers : 10; }; Or with some bit twiddling... uint32_t status = readers | (waitToRead << 10) | (writers << 20); Instead, I did what any overzealous C++ programmer does. I abused the preprocessor and templating system. BEGIN_BITFIELD_TYPE(Status, uint32_t) // type name, storage size ADD_BITFIELD_MEMBER(readers, 0, 10) // member name, offset, number of bits ADD_BITFIELD_MEMBER(waitToRead, 10, 10) ADD_BITFIELD_MEMBER(writers, 20, 10) END_BITFIELD_TYPE() The above set of macros defines a new bitfield type Status with three members. The second argument to BEGIN_BITFIELD_TYPE() must be an unsigned integer type. The second argument to ADD_BITFIELD_MEMBER() specifies each member's offset, while the third argument specifies the number of bits. I call this a safe bitfield because it performs safety checks to ensure that every operation on the bitfield fits within the available number of bits. It also supports packed arrays. I thought the technique deserved a quick explanation here, since I'm going to refer back to it in future posts. How to Manipulate a Safe Bitfield Let's take Status as an example. Simply create an object of type Status as you would any other object. By default, it's initialized to zero, but you can initialize it from any integer of the same size. In the GitHub project, it's often initialized from the result of a C++11 atomic operation. Status status = m_status.load(std::memory_order_relaxed); Setting the value of a bitfield member is easy. Just assign to the member the same way you would using a traditional bitfield. If asserts are enabled - such as in a debug build - and you try to assign a value that's too large for the bitfield, an assert will occur at runtime. It's meant to help catch programming errors during dev