Browse DevX
Sign up for e-mail newsletters from DevX


Bitwise Operators: Combining Efficiency and Ease of Use-3 : Page 3




Building the Right Environment to Support AI, Machine Learning and Deep Learning

In addition to the basic four operators shown, C++ defines three self-assigning versions thereof:
  • &= self-assigning bitwise AND
  • |= self-assigning bitwise OR
  • ^= self-assigning bitwise XOR

Thus, the previous code listing can be rewritten like this:

BYTE s1=63; // 0x3f, 0011 1111 BYTE s2=67; // 0x43, 0100 0011 s1^=s2; // equivalent to: s1 = s1 ^ s2

Two additional operators are left shift and right shift:
  • << left shift
  • >> right shift
>> shifts bits by n positions to the right. For example, if you take the string:

0011 1111 //decimal value: 63

Shifting it by one position to the right produces:

0001 1111 //decimal value: 31 BYTE s1 = 63; //0x3f, 0011 1111 BYTE result = s1 >> 1; // 0x1f, 0001 1111

A graphic illustration of this operation may demystify the underlying steps. First, you have an eight bit string whose boundaries are marked with a pair of bars:

|0011 1111|

The right shift operation causes the leftmost bit's position to become empty (indicated by an underscore). The rightmost bit overflows outside the string's boundaries:

|_0011 111|1

In the second step, the processor pads empty positions with zeros and discards bits that were pushed outside the string's boundaries (this rule applies only to unsigned types; the effect of shifting signed values is machine-dependent):

|00011 111|_

Of course, these steps don't necessarily correspond to the underlying machine instructions that your processor employs but the effect is the same. Bit shifting happens to be a very efficient operation. This is why time-critical applications often use shift operators as a faster alternative to the division and multiplication operators. In the above example, the shift operation has the same effect as dividing the original value by two. In a similar vein, you can get the effect of multiplying a number by two if you apply the left shift operator. For example, left shifting the number 63 by one position produces 126:

BYTE s1 = 63; // 0x3f, 0011 1111 BYTE res = s1 << 1; //dec 126, 0x73, 0111 1110

Using the self-assignment versions of these operators, the previous code can be rewritten like this:

BYTE s1 = 63; //0x3f, 0011 1111 // the expression 's1 >> 2;' divides s1 by 4 s1 >>= 2; // 15, 0x0f, 0000 1111

Wise Up
Bitwise operators are useful in bit masking, i.e., setting or examining bits in a bit string. Take for example a simple word processing application. The text in a document (or a portion thereof) may have the following features: bold, italics, underlined, or none. Each of these features can be represented as an individual bit:

const BYTE BOLD = 0x01; // first bit const BYTE ITAL = 0x02; // second bit const BYTE UNDERL = 0x04; // third bit

Users may combine some of these features, all of them or none:

BYTE style = BOLD | ITAL;//turn on bold and italics

The following code tests whether underline and bold are on using bit masks:

bool isul=style & UNDERL; // false bool isbold=style & BOLD; // true

Danny Kalev is a system analyst and software engineer with 13 years of experience, specializing in C++ and object-oriented analysis and design. He is a member of the ANSI C++ standardization committee and the author of ANSI/ISO C++ Professional Programmer's Handbook (Que, 1999, ISBN: 0789720221). Reach him at dannykk@inter.net.il.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date