|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionOne time I was roaming the Visual C++ forum (once again), I had to face the facts that bitwise operations, and binary in general, are rarely in beginners common sense. After having painned my fingers to write a long long answer to that innocent person, It became obvious that i had to share this obfuscated knowledge with the community through this article. if you want to get deeper knowledge about the C/C++ bitwise operators cover, you can read the very complete article An introduction to bitwise operators by PJ Arends. You can also go into a very complex (but effective) analysis of bit hacking with this article: Bit Twiddling Hacks By Sean Eron Anderson. I'm so going to present the more complete way as I can what we can do with bitwise operators, flags and all that binary stuff. The FactsOne of the places where we most find the use for this is certainly when a library provides a set of enumerations and when functions use enum { STYLE1 = 1, STYLE2 = 2, STYLE3 = 4, STYLE4 = 8, STYLE5 = 16, STYLE6 = 32, STYLE7 = 64, STYLE8 = 128 }; As we can see, these constant are all powers of 2. To understand why these constants' are chosen, we must go in binary representation : 1 -> 0b 00000000 00000000 00000000 00000001 2 -> 0b 00000000 00000000 00000000 00000010 4 -> 0b 00000000 00000000 00000000 00000100 8 -> 0b 00000000 00000000 00000000 00001000 16 -> 0b 00000000 00000000 00000000 00010000 32 -> 0b 00000000 00000000 00000000 00100000 64 -> 0b 00000000 00000000 00000000 01000000 128 -> 0b 00000000 00000000 00000000 10000000 Notice that for all of these values, only one 0b 00000000 00000000 00000000 00100101 Flags of Style1, Style3 and Style6 are set The OperatorsWe face a problem now. C++ doesn't handle binary directly. We have to use x y | x y & x ~ -------- -------- ------ 0 0 0 0 0 0 0 1 0 1 1 0 1 0 1 0 1 0 1 1 0 0 1 1 1 1 1 1 Knowing this, we can use these operators to build some mixes such as presented above. 0b 00000000 00000000 00000000 00000001 <- STYLE1 0b 00000000 00000000 00000000 00000100 <- STYLE3 0b 00000000 00000000 00000000 00100000 <- STYLE6 ----------------------------------------------- 0b 00000000 00000000 00000000 00100101 <- STYLE1 | STYLE3 | STYLE6 We can see that the bitwise DWORD in actionCommonly, such mixes stick to the Say we want to know if the bit of DWORD parameter -> 0b 00000000 00000000 00000000 00100101 STYLE8 mask -> 0b 00000000 00000000 00000000 10000000 ---------------------------------------- Bitwise AND -> 0b 00000000 00000000 00000000 00000000 <- 0x00000000 DWORD parameter -> 0b 00000000 00000000 00000000 10100101 STYLE8 mask -> 0b 00000000 00000000 00000000 10000000 ---------------------------------------- Bitwise AND -> 0b 00000000 00000000 00000000 10000000 <- STYLE8 If the OK, now, in practice, here is how you'll often see it: void SetStyles(DWORD dwStyles) { if ((STYLE1 & dwStyles) == STYLE1) { //Apply style 1 } else if ((STYLE2 & dwStyles) == STYLE2) { //Apply style 2 } else if ((STYLE3 & dwStyles) == STYLE3) { //Apply style 3 } //etc... } I didn't present the third operator NOT ( void RemoveStyle5 (DWORD& dwStyles) { if ((STYLE5 & dwStyles) == STYLE5) { dwStyles &= ~STYLE5; } } I didn't mention the XOR ( #define XOR(a,b) (((a) & ~(b)) | ((b) & ~(a)))
Anyway, this operator can be used to easily switch one bit : void SwitchStyle5 (DWORD& dwStyles) {
dwStyles ^= STYLE5;
}
LinksThe following links are for a complimentary knowledge, if you like to go deeper in bitwise handling:
ConclusionWell, here we are then. If you went here to understand these binary operations, I hope that i helped you in your way. if you came to see what was going on here, then don't hesitate to point my mistakes if any, so that i can fastly fix it. | ||||||||||||||||||||||||||||