Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


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