Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A bit field is a class or struct data member whose size is explicitly specified in bits. It allows developers to pack multiple integral variables into a single machine word, providing fine-grained control over memory layout and alignment at the bit level.

Syntax

A bit field is declared using an integral or enumeration type, followed by a colon and a constant expression representing the width in bits.
struct StructName {
    integral_type member_name : width_in_bits;
};
  • integral_type: Must be an integral type (e.g., int, unsigned int, signed int, bool, char) or an enumeration.
  • width_in_bits: A constant integer expression specifying the exact number of bits the member will occupy.

Memory Layout and Packing Behavior

When multiple bit fields are declared sequentially, the compiler attempts to pack them into the same underlying allocation unit (typically a machine word corresponding to the declared type).
struct BitLayout {
    unsigned int fieldA : 1;  // Occupies 1 bit
    unsigned int fieldB : 3;  // Occupies 3 bits
    unsigned int fieldC : 4;  // Occupies 4 bits
}; 
// Total declared bits: 8. 
// The struct size will typically be sizeof(unsigned int) (e.g., 4 bytes) due to alignment.
If a subsequent bit field cannot fit into the remaining space of the current allocation unit, the compiler’s behavior is implementation-defined. It will either split the bit field across allocation units or pad the remainder of the current unit and start the new bit field on the next alignment boundary.

Special Constructs

C++ provides two specialized syntaxes for manual memory alignment within bit field structures: 1. Unnamed Bit Fields (Padding) An unnamed bit field acts as padding. It consumes the specified number of bits but is inaccessible programmatically. 2. Zero-Width Bit Fields (Alignment) An unnamed bit field with a width of 0 forces the compiler to pad the current allocation unit to its end. The next declared bit field will begin at the start of the next allocation unit boundary.
struct AlignedLayout {
    unsigned int field1 : 4;
    unsigned int        : 4; // Unnamed padding: skips 4 bits
    unsigned int field2 : 4;
    unsigned int        : 0; // Forces alignment to the next unsigned int boundary
    unsigned int field3 : 8; // Starts at the beginning of a new unsigned int
};

Language Restrictions

Because bit fields do not necessarily align with byte boundaries, C++ imposes strict rules on their usage:
  • No Pointers: You cannot take the address of a bit field using the address-of operator (&).
  • No Non-Const References: You cannot bind a non-const reference to a bit field. You can bind a const reference, but C++ will create a temporary, fully-aligned variable of the underlying type, copy the bit field’s value into it, and bind the reference to that temporary.
  • No sizeof: The sizeof operator cannot be applied to a bit field, as sizeof evaluates to a number of bytes, not bits.
  • No Arrays: You cannot declare an array of bit fields.
  • No Static Members: A bit field cannot be declared as a static member of a class.

Signed vs. Unsigned Behavior

When using signed integral types, the highest-order bit in the specified width acts as the sign bit. This requires careful sizing. For example, a signed int bit field with a width of 1 can only represent the values 0 and -1 (in two’s complement), not 0 and 1.
struct SignedBits {
    signed int flag : 1;
};

// If flag is assigned 1, its internal representation is 0b1.
// Because it is a 1-bit signed integer, the sign bit is 1, resulting in -1.
Master C++ with Deep Grasping Methodology!Learn More