Introduction

I have noticed that some people seem to have problems with
bitwise operators, so I decided to write this brief tutorial
on how to use them.

An Introduction to bits

Bits, what are they you may ask?

Well, simply put, bits are the individual ones and zeros that
make up every thing we do with computers. All the data you use
is stored in your computer using bits. A BYTE is made up of eight bits,
a WORD is two BYTEs, or sixteen bits. And a DWORD is two WORDS, or
thirty two bits.

The beauty of having bitwise operators is that you can use a BYTE, WORD
or DWORD as a small array or structure. Using bitwise operators you can check
or set the values of individual bits or even a group of bits.

Hexadecimal numbers and how they relate to bits

When working with bits, it is kind of hard to express every number using
just ones and zeros, which is known as binary notation. To get around this we use hexadecimal (base 16) numbers.

As you may or may not know, it takes four bits to cover all the numbers from zero to fifteen,
which also happens to be the range of a single digit hexadecimal number.
This group of four bits, or half a BYTE, is called a nibble. As there are two
nibbles in a BYTE, we can use two hexadecimal digits to show the value of one BYTE.

So if we had one BYTE containing the letter 'r' (ASCII code 114) it would look like this:

01110010 binary
72 hexadecimal

We could write it as '0x72'

Bitwise operators

There are six bitwise operators. They are:
& The AND operator
| The OR operator
^ The XOR operator
~ The Ones Complement or Inversion operator
>> The Right Shift operator
<< The Left Shift operator.

The & operator

The & (AND) operator compares two values, and returns a value that
has its bits set if, and only if, the two values being compared both have their
corresponding bits set. The bits are compared using the following table

1 & 1 == 11 & 0 == 00 & 1 == 00 & 0 == 0

An ideal use for this is to set up a mask to check the values of certain bits.
Say we have a BYTE that contains some bit flags, and we want to check if bit four
bit is set.

The | operator

The | (OR) operator compares two values, and returns a value that
has its bits set if one or the other values, or both, have their corresponding bits set.
The bits are compared using the following table

1 | 1 == 11 | 0 == 10 | 1 == 10 | 0 == 0

An ideal use for this is to ensure that certain bits are set.
Say we want to ensure that bit three of some value is set

BYTE b = 50;
BYTE c = b | 0x04;
cout << "c = " << c << endl;

This would result in the following calculation

00110010 - b
| 00000100 - | 0x04
----------
00110110 - result

The ^ operator

The ^ (XOR) operator compares two values, and returns a value that
has its bits set if one or the other value has its corresponding bits set,
but not both. The bits are compared using the following table

1 ^ 1 == 01 ^ 0 == 10 ^ 1 == 10 ^ 0 == 0

An ideal use for this is to toggle certain bits. Say we want toggle the bits three and four

The ~ operator

The ~ (Ones Complement or inversion) operator acts only on one value and it inverts it,
turning all the ones int zeros, and all the zeros into ones. An ideal use of this would be to
set certain bytes to zero, and ensuring all other bytes are set to one, regardless of the size of the data.
Say we want to set all the bits to one except bits zero and one

The >> and << operators

The >> (Right shift) and << (left shift) operators move the bits the number of bit positions specified.
The >> operator shifts the bits from the high bit to the low bit.
The << operator shifts the bits from the low bit to the high bit.
One use for these operators is to align the bits for whatever reason (check out the MAKEWPARAM, HIWORD, and LOWORD macros)

Bit Fields

Another interesting thing that can be done using bits is to have bit fields.
With bit fields you can set up minature structures within a BYTE, WORD or DWORD.
Say, for example, we want to keep track of dates, but we want to use the least amount of memory as possible.
We could declare our structure this way

In this example, the day field takes up the lowest 5 bits, month the next four, and year
the next 14 bits. So we can store the date structure in twenty three bits, which
is contained in three BYTEs. The twenty fourth bit is ignored.
If I had declared it using an integer for each field, the structure would have taken up 12 BYTEs.

First we will look at the data type we are using for the bit field structure. In this case we used a BYTE.
A BYTE is 8 bits, and by using it, the compiler will allocate one BYTE for storage. If however, we
use more than 8 bits in our structure, the compiler will allocate another BYTE, as many BYTEs as it takes to hold our structure.
If we had used a WORD or DWORD, the compiler would have allocated a total of 32 bits to hold our structure.

Now lets look at how the various fields are declared. First we have the variable (day, month, and year), followed by a colon
that separates the variable from the number of bits that it contains. Each bit field is
separated by a comma, and the list is ended
with a semicolon.

Now we get to the struct declaration. We put the bit fields into a struct like this so that we can use convention
structure accessing notation to get at the structure members. Also, since we can not get the addresses of bit fields,
we can now use the address of the structure.

Comments and Discussions

Well, looks like we have similar articles again! Great minds think alike, eh?

Anyway, since I believe that our articles complement one another, would you want to cross-link them? Also, would you mind if I referenced your article in my future ones that will be meant to build upon my Learning Binary and Hexadecimal one?

BTW, if you'd like, I'd also be willing to make a downloadable PDF version for you. I have Acrobat 5 at home and just look for excuses to use it.

Jeremy Falcon wrote:Well, looks like we have similar articles again! Great minds think alike, eh?

Yeah, but mine was first this time;P

Jeremy Falcon wrote:Anyway, since I believe that our articles complement one another, would you want to cross-link them? Also, would you mind if I referenced your article in my future ones that will be meant to build upon my Learning Binary and Hexadecimal one?

You can reference this one from your articles if you like, but I will consider your note here to be a cross reference to your article. (I'm too damn lazy to bother updating my article)

Jeremy Falcon wrote:BTW, if you'd like, I'd also be willing to make a downloadable PDF version for you. I have Acrobat 5 at home and just look for excuses to use it.

It is nice of you offer, but until PDF versions of articles becomes the CP standard I will pass. But do feel free to make a PDF copy for your own personal use if you desire

Logical shifts shift in zero as the top bit. Arithmetic shifts copy the old top bit as the new top bit, as can be seen in the above example.

There is no requirement for the compiler to choose one over the other, so leaving out the '&' bit is just asking for trouble. I believe it works with the MS compiler, but I'm not sure about any others.

Ryan

Being little and getting pushed around by big guys all my life I guess I compensate by pushing electrons and holes around. What a bully I am, but I do enjoy making subatomic particles hop at my bidding - Roger Wright (2nd April 2003, The Lounge)

Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late - John Nichol "Point Of Impact"

What the deal about these Endians ? I not said Indians It's the way data is stored in MEMORY. Well, numbers such as a long/DWORD (32 bits) 0x12345678 are ALWAYS stored in BIG ENDIAN into the microprocessor registers, but in a different way into the memory according to the microprocessor firm.

Every byte is formed with 8 bits, from bit 7 to 0 (left to right).Every word is formed with 16 bits, from bit 15 to 0 (left to right)..Every long is formed with 32 bits, from bit 31 to 0 (left to right)..

BIG ENDIAN is the way we ALL write numbers on paper, most significant/powerful digit on the left (for instance thousands, then hundreds, then units). It's also the way ALL DATAS are stored in registers, for ALL processors architechtures !

It's really useful when you work in embedded systems and you debug memory mappings. What you have in registers is what you get in memory. But fetching the Low Word of the data needs to fetch it at 'n+2'. So the fetching is a bit slower due to the additive memory address shifting to fetch the 'casted' (according to the assembly opcode operand size) data.

BIG ENDIAN numbers are also widely used into TCP/IP protocols ! The most common BIG Endian architechtures are Motorola 6800 family, 68000 family and ColdFire family. The PowerPC is a little Endian one (derivated from the IBM Power processor family).

It is useful when you want to get the low part of the data, for instance the LSB or the LSW. You just have to fetch the 'casted' (according to the assembly opcode operand size) data at the same address 'n+0' ! But debuging memory is then absolutely weird...

My favorite way is the Motorola's since it is easier to first know in which format is written the number, then reading the number. For instance, when I read $1234, I immediatly know that it means 4660 in decimal format. Harder to first read 1234, then discover the number was given in hexadecimal (Intel). Toshiba's way is good also, but I sometimes find hard to read o01101 or h481 ! Characters @, $ and % cannot be missed !

However, a minor correction is needed: (so as not to confuse a beginner )-------------------------------------In the | operator usage example, the mask for setting the 3rd bit should be 0x08 [assuming bitsare counted starting from 0 (i.e., zero) as illustrated in the rest of this article]

i.e.,An ideal use for this is to ensure that certain bits are set. Say we want to ensure that bit three of some value is set

It looks strange if you have never seen it before, but it does help to reduce the conversion bugs when converting from a bit number of a hex constant.

Tim Smith

I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?

Gr88888888888888 article.I think there should be more explanation about shift operators. Can u tell me how to reverse the bytes in DWORD i.e. interchanging the position s of bytes in DWORD, last bytes come in place of first byte and so on(completely reverse the DWORD bytes).