12.5 Bit Members or Packed Structures

I l @ ve RuBoard

12.5 Bit Members or Packed Structures

So far all the structures you've been using have been unpacked . Packed structures allow you to declare structures in a way that takes up a minimum of storage. For example, the following structure takes up 6 bytes (using a 16-bit compiler):

 struct item {      unsigned int list;      // True if item is in the list     unsigned int seen;      // True if this item has been seen     unsigned int number;    // Item number }; 

The storage layout for this structure can be seen in Figure 12-3. Each structure uses 6 bytes of storage (2 bytes for each integer).

Figure 12-3. Unpacked structure
figs/c++2_1203.gif

However, the members list and seen can have only two values, 0 and 1, so only 1 bit is needed to represent them. You never plan on having more than 16383 items (0x3fff or 14 bits). You can redefine this structure using bit members, so that it takes only 2 bytes, by following each member with a colon and the number of bits to be used for that member:

 struct item {      unsigned int list:1;    // True if item is in the list     unsigned int seen:1;    // True if this item has been seen     unsigned int number:14; // Item number }; 

In this example, you tell the compiler to use 1 bit for list , 1 bit for seen and 14 bits for number . Using this method you can pack data into only 2 bytes, as seen in Figure 12-4.

Figure 12-4. Packed structure
figs/c++2_1204.gif

You can add a bit field only to an int or enum variable. It doesn't work on floating-point members, strings, or other complex types.

Packed structures should be used with care. The machine code to extract data from bit members is relatively large and slow. Unless storage is a problem, packed structures should not be used.

Also, the C++ standard does not define how packing must be implemented. The compiler is free to pack things together in any order it wants to. There is no guarantee that our structure will be stored in two 8-bit bytes. (Some cheap compilers treat packed structures the same an normal structures and leave everything unpacked. This is legal under the C++ standard.)

In Chapter 11, you needed to store character data and five status flags for 8,000 characters . In this case, using a different byte for each flag would eat up a lot of storage (five bytes for each incoming character). You used bitwise operations to pack the five flags into a single byte. Alternatively, a packed structure could have accomplished the same thing:

 struct char_and_status {      char character;     // Character from device     unsigned int error:1;        // True if any error is set     unsigned int framing_error:1;// A framing error occurred     unsigned int parity_error:1; // Character had the wrong parity     unsigned int carrier_lost:1; // The carrier signal went down     unsigned int channel_down:1; // Power was lost on the channel }; 

Using packed structures for flags is clearer and less error-prone than using bitwise operators. However, bitwise operators allow additional flexibility. You should use the approach that is clearest and easiest for you to use.

Question 12-1: Why does Example 12-1 fail?

Example 12-1. info/ info .cpp
 #include <iostream> struct info {     int valid:1;        // If 1, we are valid     int data:31;        // The data }; info a_info; int main(  ) {     a_info.valid = 1;     if (a_info.valid == 1)          std::cout << "a_info is valid\n";     return (0); } 

The GNU compiler does try to give a hint as to what's going on. Now if we could only understand what it is trying to say:

 info.cpp: In function `int main(  )': info.cpp:13: warning: comparison is always 0 due to width of bitfield 
I l @ ve RuBoard


Practical C++ Programming
Practical C Programming, 3rd Edition
ISBN: 1565923065
EAN: 2147483647
Year: 2003
Pages: 364

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