J
James Kuyper
CBFalconer said:Especially since there are no (i.e. zip) guarantees about how the
bits in bitfields are selected. Use constants and | or &.
The standard does provide a few guarantees about how bit in bitfields
are selected. Not as many as some people expect, but it's not "zip", either:
6.7.2.1p10: "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."
p11: "... a bit-field structure member with a width of 0
indicates that no further bit-field is to be packed into the unit in
which the previous bitfield, if any, was placed."
p13: "Within a structure object, the non-bit-field members and the units
in which bit-fields reside have addresses that increase in the order in
which they are declared."
Consider the following code:
struct example {
int a;
float b;
signed c:5;
signed d:3;
unsigned :0;
unsigned e:8;
double f;
} one, two;
size_t offset = offsetof(struct example, b) + sizeof one.b;
size_t width = offsetof(struct example, f) - offset
memcpy((char*)&two + offset, (char*)&one + offset, width);
Because the addressable storage unit cannot have a size of less than 8
bits, 6.7.2.1p10 guarantees that one.c and one.d share the same storage
unit.
Because of 6.7.2.1p11, one.e is guaranteed to be in a different storage
unit from one.c and one.d.
Because of 6.7.2.1p13, the call to memcpy() is guaranteed to copy the
bits representing 'c', 'd', and 'e' from 'one' to 'two'. There's no
portable way to be sure which of those bits represent each of those
variables, but they will be copied.