Bitwise operators and bit manipulation question!!!

Hello,
I am kinda new to C++ programming and i have a question about bitmanipulation and bitwise operators.
I understand how to use bitwise operators (ie. & ^ |) so i'm not really struggling how to use them per say, however im struggling to realise when and what to use them for.
I have read online that in this day and age you dont really need to use them unless you are working with hardware/microprocessors where memory usage is important, and unfortunately i am studying Electrical Engineering :( so i feel that i will come across these alot.
My lecturer said that these are powerful but never really gave us examples, and being the useless university lecturer that he is, he seems to be content on not replying to my emails. Alas, I ask that if someone would be so kind as to just give me an example as to how these can be used in a real world scenario to save memory or allocate memory, what ever they are used for.
(No real code needed, just a worded example, unless its easier to explain via code)
Thanks!
Regards,
jPytlo
The bitwise | is used very often when combining various bitmap flags:

1
2
3
4
5
6
std::cin.exceptions(std::ios_base::failbit | std::ios_base::eofbit);

p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, off);

auto handle = std::async(std::launch::async | std::launch::deferred, 
                                         parallel_sum<RAIter>, mid, end);


The & comes up similarly, when clearing bits. xor is more likely to be found in actual bitwise arithmetic, e.g. in a hash function.
Thanks!
Im not really sure what that chunk of code does :P But i get this gist of when they can be useful and the tasks they can perform.
Just another quick question, when you say combining bitmap flags are you referring to bitmaps as in computer graphics?
Thanks again for explaining when & and xor are used, i can imagine sceneries where they will be useful now!
1
2
3
4
5
6
if (number & 1){
//number is odd
}
   00000001
  &01010101
  =00000001


I believe that one of the best uses is to fit 8 bools in one byte, whereas a bool type variable normally needs all 8. If someone could show an example of that it would be neat to see.





Last edited on
Bitwise operators perform simple logic:

OR: If either or both bits is 1, result is 1. Otherwise result is zero:
1
2
3
4
0 | 0 == 0
0 | 1 == 1
1 | 0 == 1
1 | 1 == 1


AND: If both bits are 1, result is 1. Otherwise result is zero:
1
2
3
4
0 & 0 == 0
0 & 1 == 0
1 & 0 == 0
1 & 1 == 1


XOR: If either (but not both) bits are 1, result is 1. Otherwise (both bits zero, or both bits 1), result is zero:
1
2
3
4
0 ^ 0 == 0
0 ^ 1 == 1
1 ^ 0 == 1
1 ^ 1 == 0


COMPLIMENT: Effectively a bitwise "not". If the bit is 0, result is 1, otherwise result is 0:
1
2
~0 == 1
~1 == 0




The C++ operators perform these actions on each bit in the given values. For example:

1
2
3
4
5
6
7
8
9
10
int foo = 0x13 & 0x05;
cout << foo;  // prints 1

// because...
/*
0x13 = %0001 0011
0x05 = %0000 0101
---- & ----------
0x01 = %0000 0001
*/



Practical Uses: OR

OR is useful for making sure an individual bit is set. This is useful when combining "flags" as Cubbi illustrated:

1
2
3
4
5
6
7
8
9
// a flag would be a unique bit
const int flag1 = 0x01;  // %0001
const int flag2 = 0x02;  // %0010
const int flag3 = 0x04;  // %0100
const int flag4 = 0x08;  // %1000

// to combine flags:
int someflags = flag1 | flag3;
// result is:  0x05 : %0101 



The way this works is by "turning on" the desired bit, and leaving all other bits unchanged.

if we do:  someflags |= flag1;

someflags = %????
    flag1 = %0001
          | -----
            %???1 <- all bits stay unchanged except the low bit, which becomes 1


This is different from normal addition because addition will screw up the values if the flag is already set:

1
2
3
int someflags = flag1 | flag3;  //       0x05 : %0101
int good = someflags | flag3;   // still 0x05 : %0101
int bad = someflags + flag3;    // now   0x09 : %1001 


As you can see, by using addition, we've actually cleared the desired flag and set an undesired one by mistake!


Practical Uses: AND, compliment
AND is often used to see if a specific flag has been set:

1
2
3
4
if( someflags & flag1 )
{
  // here, we know flag1 is set in someflags
}


The way this works is by "turning off" all bits except the bits we're interested in (in this case, flag1's bit):

someflags = %????
    flag1 = %0001
          & -----
            %000? <- all bits become zero except for the low bit



AND can also be used with the compliment operator to "turn off" a specific bit. Kind of like the reverse of the OR operation:


if we do:  someflags &= ~flag1;

    flag1 = %0001
   ~flag1 = %1110


someflags = %????
   ~flag1 = %1110
          & -----
            %???0  <- all bits unchanged except the low bit, which is forced to zero





Practical Uses: XOR

I'm too lazy to get into how this is commonly used. XOR effectively lets you toggle a bit:

someflags ^= flag1; will set flag1 if it's clear, or clear it if it's already set.

Mostly this is used for encrypting stuff, since XOR doesn't "lose" any information. If you XOR a value with the same key twice, you get the original value.

That is:

1
2
3
4
5
6
7
int original = ...;
int key = ...;

int encypted = original ^ key;
int decrypted = encrypted ^ key;

if(original == decrypted)  // <- this will be true, regardless of what 'original' or 'key' are 
^ I vote for making that an article.
Go ahead. I'm too lazy.

Feel free to even take credit for it. I don't care about that kind of thing.
Pay thousands to go to university...Get taught better and learn more online for free. :(
Anyway! Thanks for all the help guys and a big shout out to Disch for taking the time to write up some great examples and explanations :) They really helped!
Topic archived. No new replies allowed.