A "bifield" is a set one or more bits in a "word" (that is, say an int
, long
or char
) that are stored together in one variable.
You can for example have "none, "spots" and/or "stripes" on some animal, and it can also have "none, short, medium or long" tail.
So, we need two bits to reprent the length of a tail:
enum tail
{
tail_none = 0,
tail_short = 1,
tail_medium = 2,
tail_long = 3
};
We then store these as bits in the "attributes":
enum bits_shifts
{
tail_shift = 0, // Uses bits 0..1
spots_shift = 2, // Uses bit 2
stripes_shift = 3
};
enum bits_counts
{
tail_bits = 2, // Uses bits 0..1
spots_bits = 1, // Uses bit 2
stripes_bits = 1
};
We now pretend that we have fetched from some input the tail_size and the has_stripes, has_spots variables.
int attributes;
attributes = tail_length << tail_shift;
if (has_spots)
{
attributes |= 1 << spots_shift;
}
if (has_stripes)
{
attributes |= 1 << stripes_shift;
}
Later we want to figure what the attributes are:
switch((attributes >> tail_shift) & (1 << tail_bits)-1))
{
case tail_none:
cout << "no tail";
break;
case tail_short:
cout << "short tail";
break;
case tail_medium:
cout << "medium tail";
break;
case tail_short:
cout << "long tail";
break;
}
if (attributes & (1 << stripes_shift))
{
cout << "has stripes";
}
if (attributes & (1 << spots_shift))
{
cout << "has spots";
}
Now, we have stored all this in one integer, and then "fished it out" again.
You can of course do something like this too:
enum bitfields
{
has_widget1 = 1,
has_widget2 = 2,
has_widget3 = 4,
has_widget4 = 8,
has_widget5 = 16,
...
has_widget25 = 16777216,
...
}
int widgets = has_widget1 | has_widget5;
...
if (widgets & has_widget1)
{
...
}
It is really just an easy way to pack several things into one variable.