C++, like C, enables you to specify structure members that occupy a particular number of bits. This can be handy for creating a data structure that corresponds, say, to a register on some hardware device. The field type should be an integral or enumeration type (enumerations are discussed later in this chapter), and a colon followed by a number indicates the actual number of bits to be used. You can use unnamed fields to provide spacing. Each member is termed a
struct torgle_register
{
unsigned int SN : 4; // 4 bits for SN value
unsigned int : 4; // 4 bits unused
bool goodIn : 1; // valid input (1 bit)
bool goodTorgle : 1; // successful torgling
};
You can initialize the fields in the usual manner, and you use standard structure notation to access bit fields:
torgle_register tr = { 14, true, false };
...
if (tr.goodIn) // if statement covered in Chapter 6
...
Bit fields are typically used in low-level programming. Often, using an integral type and the bitwise operators listed in Appendix E, “Other Operators,” provides an alternative approach.
Unions
A
union one4all
{
int int_val;
long long_val;
double double_val;
};
You can use a one4all variable to hold an int, a long, or a double, just as long as you do so at different times:
one4all pail;
pail.int_val = 15; // store an int
cout << pail.int_val;
pail.double_val = 1.38; // store a double, int value is lost
cout << pail.double_val;
Thus, pail can serve as an int variable on one occasion and as a double variable at another time. The member name identifies the capacity in which the variable is acting. Because a union holds only one value at a time, it has to have space enough to hold its largest member. Hence, the size of the union is the size of its largest member.
One use for a union is to save space when a data item can use two or more formats but never simultaneously. For example, suppose you manage a mixed inventory of widgets, some of which have an integer ID, and some of which have a string ID. In that case, you could use the following:
struct widget
{
char brand[20];
int type;
union id // format depends on widget type
{
long id_num; // type 1 widgets
char id_char[20]; // other widgets
} id_val;
};
...
widget prize;
...
if (prize.type == 1) // if-else statement (Chapter 6)
cin >> prize.id_val.id_num; // use member name to indicate mode
else
cin >> prize.id_val.id_char;
An
struct widget
{
char brand[20];
int type;
union // anonymous union
{
long id_num; // type 1 widgets
char id_char[20]; // other widgets
};
};
...
widget prize;
...
if (prize.type == 1)
cin >> prize.id_num;
else
cin >> prize.id_char;
Because the union is anonymous, id_num and id_char are treated as two members of prize that share the same address. The need for an intermediate identifier
Unions often (but not exclusively) are used to save memory space. That may not seem that necessary in these days of gigabytes of RAM and terabytes of storage, but not all C++ programs are written for such systems. C++ also is used for embedded systems, such as the processors used to control a toaster oven, an MP3 player, or a Mars rover. In these applications space may be at a premium. Also unions often are used when working with operating systems or hardware data structures.
Enumerations
The C++ enum facility provides an alternative to const for creating symbolic constants. It also lets you define new types but in a fairly restricted fashion. The syntax for enum resembles structure syntax. For example, consider the following statement:
enum spectrum {red, orange, yellow, green, blue, violet, indigo, ultraviolet};
This statement does two things:
• It makes spectrum the name of a new type; spectrum is termed an
• It establishes red, orange, yellow, and so on, as symbolic constants for the integer values 0–7. These constants are called
By default, enumerators are assigned integer values starting with 0 for the first enumerator, 1 for the second enumerator, and so forth. You can override the default by explicitly assigning integer values. You’ll see how later in this chapter.
You can use an enumeration name to declare a variable of the enumeration type:
spectrum band; // band a variable of type spectrum