Bit Fields

C++ provides the ability to specify the number of bits in which an integral type or enum type member of a class or a structure is stored. Such a member is referred to as a bit field. Bit fields enable better memory utilization by storing data in the minimum number of bits required. Bit field members must be declared as an integral or enum type.

Performance Tip 22.2

Bit fields help conserve storage.

Consider the following structure definition:

struct BitCard
{
 unsigned face : 4;
 unsigned suit : 2;
 unsigned color : 1;
}; // end struct BitCard

The definition contains three unsigned bit fieldsface, suit and colorused to represent a card from a deck of 52 cards. A bit field is declared by following an integral type or enum type member with a colon (:) and an integer constant representing the width of the bit field (i.e., the number of bits in which the member is stored). The width must be an integer constant.

The preceding structure definition indicates that member face is stored in 4 bits, member suit in 2 bits and member color in 1 bit. The number of bits is based on the desired range of values for each structure member. Member face stores values between 0 (Ace) and 12 (King)4 bits can store a value between 0 and 15. Member suit stores values between 0 and 3 (0 = Diamonds, 1 = Hearts, 2 = Clubs, 3 = Spades)2 bits can store a value between 0 and 3. Finally, member color stores either 0 (Red) or 1 (Black)1 bit can store either 0 or 1.

The program in Figs. 22.1422.16 creates array deck containing 52 BitCard structures (line 21 of Fig. 22.14). The constructor inserts the 52 cards in the deck array, and function deal prints the 52 cards. Notice that bit fields are accessed exactly as any other structure member is (lines 1820 and 2833 of Fig. 22.15). The member color is included as a means of indicating the card color on a system that allows color displays.

Figure 22.14. Header file for class DeckOfCards.

 1 // Fig. 22.14: DeckOfCards.h
 2 // Definition of class DeckOfCards that
 3 // represents a deck of playing cards.
 4
 5 // BitCard structure definition with bit fields
 6 struct BitCard 
 7 { 
 8  unsigned face : 4; // 4 bits; 0-15 
 9  unsigned suit : 2; // 2 bits; 0-3 
10  unsigned color : 1; // 1 bit; 0-1 
11 }; // end struct BitCard 
12
13 // DeckOfCards class definition
14 class DeckOfCards
15 {
16 public:
17 DeckOfCards(); // constructor initializes deck
18 void deal(); // deals cards in deck
19
20 private:
21 BitCard deck[ 52 ]; // represents deck of cards
22 }; // end class DeckOfCards

Figure 22.15. Class file for DeckOfCards.

(This item is displayed on pages 1075 - 1076 in the print version)

 1 // Fig. 22.15: DeckOfCards.cpp
 2 // Member-function definitions for class DeckOfCards that simulates
 3 // the shuffling and dealing of a deck of playing cards.
 4 #include 
 5 using std::cout;
 6 using std::endl;
 7
 8 #include 
 9 using std::setw;
10
11 #include "DeckOfCards.h" // DeckOfCards class definition
12
13 // no-argument DeckOfCards constructor intializes deck
14 DeckOfCards::DeckOfCards()
15 {
16 for ( int i = 0; i <= 51; i++ )
17 {
18 deck[ i ].face = i % 13; // faces in order 
19 deck[ i ].suit = i / 13; // suits in order 
20 deck[ i ].color = i / 26; // colors in order
21 } // end for
22 } // end no-argument DeckOfCards constructor
23
24 // deal cards in deck
25 void DeckOfCards::deal()
26 {
27 for ( int k1 = 0, k2 = k1 + 26; k1 <= 25; k1++, k2++ )
28 cout << "Card:" << setw( 3 ) << deck[ k1 ].face
29 << " Suit:" << setw( 2 ) << deck[ k1 ].suit
30 << " Color:" << setw( 2 ) << deck[ k1 ].color
31 << " " << "Card:" << setw( 3 ) << deck[ k2 ].face
32 << " Suit:" << setw( 2 ) << deck[ k2 ].suit
33 << " Color:" << setw( 2 ) << deck[ k2 ].color << endl;
34 } // end function deal

Figure 22.16. Bit fields used to store a deck of cards.

(This item is displayed on page 1077 in the print version)

 1 // Fig. 22.16: fig22_16.cpp
 2 // Card shuffling and dealing program.
 3 #include "DeckOfCards.h" // DeckOfCards class definition
 4
 5 int main()
 6 {
 7 DeckOfCards deckOfCards; // create DeckOfCards object
 8 deckOfCards.deal(); // deal the cards in the deck
 9 return 0; // indicates successful termination
10 } // end main
 
 Card: 0 Suit: 0 Color: 0 Card: 0 Suit: 2 Color: 1
 Card: 1 Suit: 0 Color: 0 Card: 1 Suit: 2 Color: 1
 Card: 2 Suit: 0 Color: 0 Card: 2 Suit: 2 Color: 1
 Card: 3 Suit: 0 Color: 0 Card: 3 Suit: 2 Color: 1
 Card: 4 Suit: 0 Color: 0 Card: 4 Suit: 2 Color: 1
 Card: 5 Suit: 0 Color: 0 Card: 5 Suit: 2 Color: 1
 Card: 6 Suit: 0 Color: 0 Card: 6 Suit: 2 Color: 1
 Card: 7 Suit: 0 Color: 0 Card: 7 Suit: 2 Color: 1
 Card: 8 Suit: 0 Color: 0 Card: 8 Suit: 2 Color: 1
 Card: 9 Suit: 0 Color: 0 Card: 9 Suit: 2 Color: 1
 Card: 10 Suit: 0 Color: 0 Card: 10 Suit: 2 Color: 1
 Card: 11 Suit: 0 Color: 0 Card: 11 Suit: 2 Color: 1
 Card: 12 Suit: 0 Color: 0 Card: 12 Suit: 2 Color: 1
 Card: 0 Suit: 1 Color: 0 Card: 0 Suit: 3 Color: 1
 Card: 1 Suit: 1 Color: 0 Card: 1 Suit: 3 Color: 1
 Card: 2 Suit: 1 Color: 0 Card: 2 Suit: 3 Color: 1
 Card: 3 Suit: 1 Color: 0 Card: 3 Suit: 3 Color: 1
 Card: 4 Suit: 1 Color: 0 Card: 4 Suit: 3 Color: 1
 Card: 5 Suit: 1 Color: 0 Card: 5 Suit: 3 Color: 1
 Card: 6 Suit: 1 Color: 0 Card: 6 Suit: 3 Color: 1
 Card: 7 Suit: 1 Color: 0 Card: 7 Suit: 3 Color: 1
 Card: 8 Suit: 1 Color: 0 Card: 8 Suit: 3 Color: 1
 Card: 9 Suit: 1 Color: 0 Card: 9 Suit: 3 Color: 1
 Card: 10 Suit: 1 Color: 0 Card: 10 Suit: 3 Color: 1
 Card: 11 Suit: 1 Color: 0 Card: 11 Suit: 3 Color: 1
 Card: 12 Suit: 1 Color: 0 Card: 12 Suit: 3 Color: 1
 

It is possible to specify an unnamed bit field, in which case the field is used as padding in the structure. For example, the structure definition uses an unnamed 3-bit field as paddingnothing can be stored in those 3 bits. Member b is stored in another storage unit.

struct Example
{
 unsigned a : 13;
 unsigned : 3; // align to next storage-unit boundary
 unsigned b : 4;
}; // end struct Example

An unnamed bit field with a zero width is used to align the next bit field on a new storage-unit boundary. For example, the structure definition

struct Example
{
 unsigned a : 13;
 unsigned : 0; // align to next storage-unit boundary
 unsigned b : 4;
}; // end struct Example

uses an unnamed 0-bit field to skip the remaining bits (as many as there are) of the storage unit in which a is stored and align b on the next storage-unit boundary.


Portability Tip 22.5

Bit-field manipulations are machine dependent. For example, some computers allow bit fields to cross word boundaries, whereas others do not.

Common Programming Error 22.6

Attempting to access individual bits of a bit field with subscripting as if they were elements of an array is a compilation error. Bit fields are not "arrays of bits."

Common Programming Error 22.7

Attempting to take the address of a bit field (the & operator may not be used with bit fields because a pointer can designate only a particular byte in memory and bit fields can start in the middle of a byte) is a compilation error.


Performance Tip 22.3

Although bit fields save space, using them can cause the compiler to generate slower-executing machine-language code. This occurs because it takes extra machine-language operations to access only portions of an addressable storage unit. This is one of many examples of the space-time trade-offs that occur in computer science.






C++ How to Program
C++ How to Program (5th Edition)
ISBN: 0131857576
EAN: 2147483647
Year: 2004
Pages: 627
Simiral book on Amazon

Flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net