From cppreference.com
Declares a class data member with explicit size, in bits. Adjacent bit-field members may (or may not) be packed to share and straddle the individual bytes.
A bit-field declaration is a
which uses the following declarator:
identifier(optional)attr(optional):size(1) identifier(optional)attr(optional):sizebrace-or-equal-initializer(2) (since C++20)The type of the bit-field is introduced by the decl-specifier-seq of the
.
attr- (since C++11) sequence of any number of
identifier- the name of the bit-field that is being declared. The name is optional: unnamed bit-fields introduce the specified number of
. size- an
with a value greater or equal to zero. When greater than zero, this is the number of bits that this bit-field will occupy. The value zero is only allowed for nameless bit-fields and has
. brace-or-equal-initializer-
to be used with this bit-field Explanation
The type of a bit-field can only be integral (including bool) or (possibly cv-qualified) enumeration type, an unnamed bit-field cannot be declared with a cv-qualified type.
A bit-field cannot be a
.
There are no bit-field
: lvalue-to-rvalue conversion always produces an object of the underlying type of the bit-field.
The number of bits in a bit-field sets the limit to the range of values it can hold:
Run this code
#include<iostream>structS{// three-bit unsigned field, allowed values are 0...7unsignedintb:3;};intmain(){Ss={6};++s.b;// store the value 7 in the bit-fieldstd::cout<<s.b<<'\n';++s.b;// the value 8 does not fit in this bit-fieldstd::cout<<s.b<<'\n';// formally implementation-defined, typically 0}Possible output:
7 0 Multiple adjacent bit-fields are usually packed together (although this behavior is implementation-defined):
Run this code
#include<bit>#include<cstdint>#include<iostream>structS{// will usually occupy 2 bytes:unsignedcharb1:3;// 1st 3 bits (in 1st byte) are b1unsignedchar:2;// next 2 bits (in 1st byte) are blocked out as unusedunsignedcharb2:6;// 6 bits for b2 - doesn't fit into the 1st byte => starts a 2ndunsignedcharb3:2;// 2 bits for b3 - next (and final) bits in the 2nd byte};intmain(){std::cout<<sizeof(S)<<'\n';// usually prints 2Ss;// set distinguishable field valuess.b1=0b111;s.b2=0b101111;s.b3=0b11;// show layout of fields in Sautoi=std::bit_cast<std::uint16_t>(s);// usually prints 1110000011110111// breakdown is: └┬┘├┘└┬┘└─┬──┘└┤// b1 u a b2 b3// where “u” marks the unused :2 specified in the struct, and// “a” marks compiler-added padding to byte-align the next field.// Byte-alignment is happening because b2's type is declared unsigned char;// if b2 were declared uint16_t there would be no “a”, b2 would abut “u”.for(autob=i;b;b>>=1)// print LSB-firststd::cout<<(b&1);std::cout<<'\n';}Possible output:
2 1110000011110111 The special unnamed bit-field of size zero can be forced to break up padding. It specifies that the next bit-field begins at the beginning of its allocation unit:
Run this code
#include<iostream>structS{// will usually occupy 2 bytes:// 3 bits: value of b1// 5 bits: unused// 2 bits: value of b2// 6 bits: unusedunsignedcharb1:3;unsignedchar:0;// start a new byteunsignedcharb2:2;};intmain(){std::cout<<sizeof(S)<<'\n';// usually prints 2// would usually print 1 if not for// the padding break in line 11}Possible output:
2 If the specified size of the bit-field is greater than the size of its type, the value is limited by the type: a std::uint8_tb:1000; would still hold values in the range [0, 255]. The extra bits are
.
Because bit-fields do not necessarily begin at the beginning of a byte, address of a bit-field cannot be taken. Pointers and non-const references to bit-fields are not possible. When
initializing a const reference
from a bit-field, a temporary is created (its type is the type of the bit-field), copy initialized with the value of the bit-field, and the reference is bound to that temporary.
There are no
for bit-fields: intb:1=0; and intb:1{0} are ill-formed.
(until C++20) In case of ambiguity between the size of the bit-field and the default member initializer, the longest sequence of tokens that forms a valid size is chosen:
inta;constintb=0;structS{// simple casesintx1:8=42;// OK; "= 42" is brace-or-equal-initializerintx2:8{42};// OK; "{42}" is brace-or-equal-initializer// ambiguitiesinty1:true?8:a=42;// OK; brace-or-equal-initializer is absentinty2:true?8:b=42;// error: cannot assign to const intinty3:(true?8:b)=42;// OK; "= 42" is brace-or-equal-initializerintz:1||newint{0};// OK; brace-or-equal-initializer is absent};(since C++20)Notes
The following properties of bit-fields are implementation-defined:
The value that results from assigning or initializing a signed bit-field with a value out of range, or from incrementing a signed bit-field past its range.
Everything about the actual allocation details of bit-fields within the class object.
For example, on some platforms, bit-fields don't straddle bytes, on others they do.
Also, on some platforms, bit-fields are packed left-to-right, on others right-to-left.
of bit-fields.
In the C programming language, the width of a bit-field cannot exceed the width of the underlying type, and whether int bit-fields that are not explicitly signed or unsigned are signed or unsigned is implementation-defined. For example, intb:3; may have the range of values [0, 7] or [-4, 3] in C, but only the latter choice is allowed in C++.
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR Applied to Behavior as published Correct behavior
C++98 it was unspecified whether the return value
of an assignment to a bit-field is a bit-field added bit-field specifications for
operators which may return lvalues
C++98 signedness of bit-fields that are neither declared
signed nor unsigned were implementation-defined consistent with underlying types
C++98 unnamed bit-fields could be declared with a cv-qualified type prohibited
C++98 cv-qualifications were not allowed in bit-field types bit-fields can have cv-qualified
enumeration types References
C++23 standard (ISO/IEC 14882:2024):
11.4.10 Bit-fields [class.bit]
C++20 standard (ISO/IEC 14882:2020):
11.4.9 Bit-fields [class.bit]
C++17 standard (ISO/IEC 14882:2017):
12.2.4 Bit-fields [class.bit]
C++14 standard (ISO/IEC 14882:2014):
9.6 Bit-fields [class.bit]
C++11 standard (ISO/IEC 14882:2011):
9.6 Bit-fields [class.bit]
C++03 standard (ISO/IEC 14882:2003):
9.6 Bit-fields [class.bit]
C++98 standard (ISO/IEC 14882:1998):
9.6 Bit-fields [class.bit]
See also