Both C and C++ allow integer members to be stored into memory spaces smaller than the compiler would ordinarily allow. These space-saving structure members are called bit fields, and their width in bits can be explicitly declared. Bit fields are used in programs that must force a data structure to correspond to a fixed hardware representation and are unlikely to be portable.
The syntax for declaring a bit field is as follows:
>>-type_specifier--+------------+--:--constant_expression--;--->< '-declarator-'
A bit field declaration contains a type specifier followed by an optional declarator, a colon, a constant integer expression that indicates the field width in bits, and a semicolon. A bit field declaration may not use either of the type qualifiers, const or volatile.
The C99 standard requires the allowable data types for a bit field to
include qualified and unqualified _Bool, signed int, and
unsigned int. In addition, this implementation supports the
following types.
In all implementations, the default integer type for a bit field is unsigned.
C++ extends the list of allowable types for bit fields to include any
integral type or enumeration type.
In either language, when you assign a value that is out of range to a bit field, the low-order bit pattern is preserved and the appropriate bits are assigned.
Bit fields with a length of 0 must be unnamed. Unnamed bit fields cannot be referenced or initialized. A zero-width bit field can cause the next field to be aligned on the next container boundary where the container is the same size as the underlying type of the bit field.
Bit fields are also subject to the align compiler option.
Each of the align suboptions gives a different set of alignment properties to
the bit fields. For a full discussion of the align compiler
option and the #pragmas affecting alignment, see XL
C/C++ Compiler Reference.
The maximum bit-field length is 64 bits. For portability, do not use
bit fields greater than 32 bits in size.
The following restrictions apply to bit fields. You cannot:
The following structure has three bit-field members kingdom, phylum, and genus, occupying 12, 6, and 2 bits respectively:
struct taxonomy { int kingdom : 12; int phylum : 6; int genus : 2; };
Alignment of Bit Fields
If a series of bit fields does not add up to the size of an int, padding can take place. The amount of padding is determined by the alignment characteristics of the members of the structure.
The following example demonstrates padding, and is valid for all implementations. Suppose that an int occupies 4 bytes. The example declares the identifier kitchen to be of type struct on_off:
struct on_off { unsigned light : 1; unsigned toaster : 1; int count; /* 4 bytes */ unsigned ac : 4; unsigned : 4; unsigned clock : 1; unsigned : 0; unsigned flag : 1; } kitchen ;
The structure kitchen contains eight members totalling 16
bytes. The following table describes the storage that each member
occupies:
Member Name | Storage Occupied |
---|---|
light | 1 bit |
toaster | 1 bit |
(padding -- 30 bits) | To the next int boundary |
count | The size of an int (4 bytes) |
ac | 4 bits |
(unnamed field) | 4 bits |
clock | 1 bit |
(padding -- 23 bits) | To the next int boundary (unnamed field) |
flag | 1 bit |
(padding -- 31 bits) | To the next int boundary |
All references to structure fields must be fully qualified. For instance, you cannot reference the second field by toaster. You must reference this field by kitchen.toaster.
The following expression sets the light field to 1:
kitchen.light = 1;
When you assign to a bit field a value that is out of its range, the bit pattern is preserved and the appropriate bits are assigned. The following expression sets the toaster field of the kitchen structure to 0 because only the least significant bit is assigned to the toaster field:
kitchen.toaster = 2;
Related References