Bit-fields

From cppreference.com
< c‎ | language

Declares a member with explicit width, in bits. Adjacent bit-field members may be packed to share and straddle the individual bytes.

A bit-field declaration is a struct or union member declaration which uses the following declarator

identifier (optional) : width
identifier - a name of the bit-field that is being declared. The name is optional: nameless bit-fields introduce the specified number of bits of padding
width - an integer constant expression

Explanation

Bit-fields can have only one of the following (possibly const or volatile qualified) types:

  • unsigned int, for unsigned bit-fields (e.g. unsigned int b : 3; has the range [ 0 7 ]
  • signed int, for signed bit-fields (signed int b : 3; has the range [ -4 3 ]
  • int, for bit-fields with implementation-defined signedness (note that this differs from the meaning of the keyword int everywhere else, where it means "signed int"). For example, int b : 3; may have the range of values [ 0 7 ] or [ -4 3 ]
  • _Bool, for single-bit bit-fields (e.g. bool x : 1;) has the range [ 0 1 ] and implicit conversions
(since C99)
  • bit-precise integer types (e.g. _BitInt(5) : 4; has the range [ -8 7 ] and unsigned _BitInt(5) : 4; has the range [ 0 15 ]
(since C23)

Additional implementation-defined types may be acceptable. It is also implementation-defined whether a bit-field may have atomic type. (since C11) The number of bits in a bit-field (width

#include <stdio.h>
 
struct S
{
    // three-bit unsigned field,
    // allowed values are 0...7
    unsigned int b : 3;
};
 
int main(void)
{
    struct S s = {7};
    ++s.b; // unsigned overflow
    printf("%d\n", s.b); // output: 0
}

Multiple adjacent bit-fields are permitted to be (and usually are) packed together:

#include <stdio.h>
 
struct S
{
    // will usually occupy 4 bytes:
    // 5 bits: value of b1
    // 11 bits: unused
    // 6 bits: value of b2
    // 2 bits: value of b3
    // 8 bits: unused
    unsigned b1 : 5, : 11, b2 : 6, b3 : 2;
};
 
int main(void)
{
    printf("%zu\n", sizeof(struct S)); // usually prints 4
}

The special unnamed bit-field of width zero breaks up padding: it specifies that the next bit-field begins at the beginning of the next allocation unit:

#include <stdio.h>
 
struct S
{
    // will usually occupy 8 bytes:
    // 5 bits: value of b1
    // 27 bits: unused
    // 6 bits: value of b2
    // 15 bits: value of b3
    // 11 bits: unused
    unsigned b1 : 5;
    unsigned    : 0; // starts a new unsigned int
    unsigned b2 : 6;
    unsigned b3 : 15;
};
 
int main(void)
{
    printf("%zu\n", sizeof(struct S)); // usually prints 8
}

Because bit-fields do not necessarily begin at the beginning of a byte, address of a bit-field cannot be taken. Pointers to bit-fields are not possible. Bit-fields cannot be used with sizeof and _Alignas (since C11)(until C23) alignas(since C23) (since C11)

Notes

The following usages of bit-fields causes undefined behavior:

The following properties of bit-fields are unspecified:

  • Alignment of the allocation unit that holds a bit-field.

The following properties of bit-fields are implementation-defined:

  • Whether bit-fields of type int are treated as signed or unsigned.
  • Whether types other than int, signed int, unsigned int , _Bool(since C99) , and (possibly unsigned) _BitInt(N) (since C23)
  • Whether atomic types are permitted.
(since C11)
  • Whether a bit-field can straddle an allocation unit boundary.
  • The order of bit-fields within an allocation unit (on some platforms, bit-fields are packed left-to-right, on others right-to-left).

Even though the number of bits in the object representation of _Bool is at least CHAR_BIT, the width of the bit-field of type _Bool cannot be greater than 1

(since C99)

In the C++ programming language, the width of a bit-field can exceed the width of the underlying type (but the extra bits are padding bits), and bit-fields of type int

References

  • C23 standard (ISO/IEC 9899:2024):
  • 6.7.2.1 Structure and union specifiers
  • C17 standard (ISO/IEC 9899:2018):
  • 6.7.2.1 Structure and union specifiers
  • C11 standard (ISO/IEC 9899:2011):
  • 6.7.2.1 Structure and union specifiers
  • C99 standard (ISO/IEC 9899:1999):
  • 6.7.2.1 Structure and union specifiers
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 3.5.2.1 Structure and union specifiers

See also

C++ documentation for Bit-field