You already know that computers store data in individual electronic cells that are in one of two states, sometimes callled ON and OFF. Also, that these two states are represented by the binary digits 1 and 0. In practical programming you often disregard this fact, and write code that deals with numbers, charac-ters, boolean values, and strings. Storing a number in a variable of type double, or a name in a String object, does not usually require dealing with individual bits. However, there are times when the code needs to know the state of one or more data bits, or needs to change individual bits or groups of bits.
One of the reasons for manipulating individual bits or bit fields is simple economics. Suppose that you were writing an operating system program and needed to keep track of the input and output devices present in the machine.
For example, your code may need to determine and store the following in-formation:
• The number of printers (range 0 to 3).
• If there is a mouse installed (yes or no).
• The number of serial ports (range 0 to 7).
• If the Pentium CPU is equipped with MMX technology (yes or no).
One way to store this information would be in conventional variables.
You could declare the following variable types:
int printers;
boolean mousePresent;
int serialPorts;
boolean hasMMX;
One objection to storing each value in an individual variable is the wasted space. When we devote an int variable for storing the number of printers connected to the system, we are wasting considerable storage space. An int variable consists of four memory bytes (refer toTable 4-1).
This means that you can store over 2 million combinations in an int type.
However, in this particular example the maximum number of printers is 3. You could use a variable of type byte or short but there would still be considerable waste. The same applies to all other data types previously listed.
Amore economical option, memory wise, would be to devote to each item the minimum amount of storage necessary for encoding all possible states. In the case of the number of printers you could do this with just two bits. Two bits allow representing values from 0 to 3, which is suffi-cient for this data element. By the same token, a single bit would serve to record if a mouse is present or not. The convention in this case is that a binary 1 represents YES and a binary 0 represents NO. The number of se-rial ports (range 0 to 5) could be encoded in a three-bit field, while an-other single bit would record the presence or absence of MMX technology in the Pentium CPU. The total storage would be as follows:
• printers, 2 bits
• mouse present, 1 bit
• serial ports, 3 bits
• MMX present, 1 bit
Incidentally...
The Multimedia Extension (MMX) is a modification of the architec-ture of the Pentium CPU used in the PC. The MMX provides an ex-tended set of instructions that facilitate programming and enhance the performance of graphics, multimedia, and other high-perfor-mance applications.
The total storage required is seven bits.Figure 8-1(on the next page) shows how the individual bits of a byte variable can be assigned to store this information.
Figure 8-1 Bitmapped Data
The operation of assigning individual bits and bit fields is called bitmapping. Another advantage of bitmapped data is that several items of information can be encoded in a single storage element. Since bitmapped data is more compact, it is easier to pass and retrieve information. For ex-ample, you could devote a byte variable to store the bitmapped data in Figure 8-1. The variable could be defined as follows:
byte systemDevices;
In order to manipulate bitmapped data you must be able to access indi-vidual bits and bit fields. This is the function of the Java bitwise opera-tors.
InTable 8-2, the operators &, |, ^, and ~ perform bitwise functions on individual bits. The convention that a binary 1 corresponds to logical true, and a binary 0 to false, allows using binary numbers to show the re-sults of a logical or bitwise operation. For example:
Printers field:
00 = 0 printers 01 = 1 printer 10 = 2 printers 11 = 3 printers
Serial ports field:
000 = 0 serial ports 001 = 1 serial port 010 = 2 serial ports . . .
111 = 7 serial ports Mouse present bit:
0 = no mouse 1 = mouse installed
UNUSED
MMX present bit:
0 = no MMX 1 = MMX available
7 6 5 4 3 2 1 0
bitsTable 8-2 Java Bitwise Operators
OPERATOR ACTION
& bitwise AND
| bitwise OR
^ bitwise XOR
~ bitwise NOT
< bitwise left-shift
> bitwise right-shift
>> bitwise unsigned right-shift
1 AND 0 = 0 1 AND 1 = 1 1 OR 0 = 1 NOT 1 = 0
Atable that lists all possible results of a bitwise or logical operation is called a truth table.Table 8-3has the truth tables for AND, OR, XOR, and NOT. The tables are valid for both logical and the bitwise operations.
Table 8-3 Logical Truth Tables
When using logical and bitwise operators you must keep in mind that although they perform similar functions, the logical operators do not change the actual contents of the variables. The bitwise operators, on the other hand, manipulate bit data. Thus, the result of a bitwise operation is a variable with a value different from the previous one.
Programmers note:
It is customary to number the bits in an operand from right-to-left with the rightmost bit designated as bit number 0. Refer toFigure 3-2.
AND OR XOR NOT
0 0 0 0 0 0 0 0 0 0 1
0 1 0 0 1 1 0 1 1 1 0
1 0 0 1 0 1 1 0 1
1 1 1 1 1 1 1 1 0