What does a colon in a struct declaration mean, such as :1, :7, :16, or :32?

What does the following C++ code mean?

unsigned char a : 1; 
unsigned char b : 7;

I guess it creates two char a and b, and both of them should be one byte long, but I have no idea what the ": 1" and ": 7" part does.


The 1 and the 7 are bit sizes to limit the range of the values. They're typically found in structures and unions. For example, on some systems (depends on char width and packing rules, etc), the code:

typedef struct {
    unsigned char a : 1;
    unsigned char b : 7;
} tOneAndSevenBits;

creates an 8-bit value, one bit for a and 7 bits for b.

Typically used in C to access "compressed" values such as a 4-bit nybble which might be contained in the top half of an 8-bit char:

typedef struct {
    unsigned char leftFour  : 4;
    unsigned char rightFour : 4;
} tTwoNybbles;

For the language lawyers amongst us, the 9.6 section of the C++11 standard explains this in detail, slightly paraphrased:


Bit-fields [class.bit]

A member-declarator of the form

     identifieropt   attribute-specifieropt   :   constant-expression

specifies a bit-field; its length is set off from the bit-field name by a colon. The optional attribute-specifier appertains to the entity being declared. The bit-field attribute is not part of the type of the class member.

The constant-expression shall be an integral constant expression with a value greater than or equal to zero. The value of the integral constant expression may be larger than the number of bits in the object representation of the bit-field’s type; in such cases the extra bits are used as padding bits and do not participate in the value representation of the bit-field.

Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit.

Note: bit-fields straddle allocation units on some machines and not on others. Bit-fields are assigned right-to-left on some machines, left-to-right on others. - end note


I believe those would be bitfields.


Strictly speaking, a bitfield must be a int, unsigned int, or _Bool. Although most compilers will take any integral type.

Ref C11 6.7.2.1:

A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type.

Your compiler will probably allocate 1 byte of storage, but it is free to grab more.

Ref C11 6.7.2.1:

An implementation may allocate any addressable storage unit large enough to hold a bit- field.

The savings comes when you have multiple bitfields that are declared one after another. In this case, the storage allocated will be packed if possible.

Ref C11 6.7.2.1:

If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined.