A LITTLE BIT ABOUT MANIPULATING LITTLE BITS
It is not unlikely that you read, in the help file, about those BIT…() functions. Right, this article is about bitAND(), bitOR(), bitNOT() and bitXOR() functions. Let’s dig into those bits a bit deeper in this article.
A Bit of History about Bits
Bits can represent any number we use in the PC. If you group those bits by eight you get a byte (yeah, right, an abbreviation of “by eight”).
Already in the days of DOS (DISK operating system, not DEAD operating system) those bytes where used for standardization. However it was not really in those 0-1 settings but in ASCII. Actually those bytes still are very much present these days. Looking at the black spots on this screen, those cute things we call letters, we look at an understandable form, for humans, of bytes.
These bytes are grouped into two groups of 4 bits. So it looks like: 0000 0000. Every bit represents an ON value (1) or an OFF value (0). Also, the position of the bit represents a value. Different from the way we read, the bits are read from right to left. In the following table I first give the values of every bit in decimals with its binary representation.
0000 0000 0 0000 0001 1 0000 0010 2 0000 0100 4 0000 1000 8 0001 0000 16 0010 0000 32 0100 0000 64 1000 0000 128 1111 1111 128+64+32+16+8+4+2+1 = 255
There are 255 items in the ASCII list...
Now, lets try some combinations. In the following table, you'll find the numbers 0 to 10 and their binary representation.
0000 0000 0 0000 0001 1 0000 0010 2 0000 0011 3 0000 0100 4 0000 0101 5 0000 0110 6 0000 0111 7 0000 1000 8 0000 1001 9 0000 1010 10
It takes only a bit of imagination to see the possibilities here. Give every combination its own value and you're all set. 255 characters to play with. I created these two tables to show what the bit values are.
A bit about logical statements
If I make a statement like: “Boudewijn is a male”, you might agree (I hope). In xBase Boudewijn=male would return a .T. value. This sets a bit from 0 to 1.
If I state, “Boudewijn is only 20 years old” you might consider this a lie (even though I behave like a young dog, so my wife complained yesterday ;-) ). Once more in xBase this would be like BoudewijnAge=20, and it would return a .F. value. This sets a bit to 0.
With an AND statement I could say: “Boudewijn is a male AND his age is 20”. As you know the first bit is true, the second is not (and I’m not gonna tell you WHAT my age is!) This would return a .F. as only a bit would be set to 1 if BOTH were true. A statement with an OR could be like: “Boudewijn is a male OR his age is 20” would return a .T. Either one of these statements is true so a true will be returned.
A bit more about logical problems
This could give an interesting conversation. What If I go to friends and they say: “Boudewijn, I’m told that do you like tea OR that you like cigars!”. I’m in trouble here; I like tea, but not a cigar! However, as one statement is true and the other is not I would, logically, have to say that this is true. Imagine their face if they offer me a cigar and I refuse!
Comparing Bits a bit
Now that you see the play with bits let’s compare them bit-by-bit… We do so by using the above mentioned functions. Lets look at two different bit-values:
0101 is the binary representation of 5.
1001 is the binary representation of 9.
Lets put them in a table and compare them.
0 1 0 1 1 0 0 1
(= decimal 1)
0 AND 1
is a comparison between .T. AND .F., so this returns a .F. value (0).
0 AND 0
is a comparison between .F. AND .F., and even if you tell two lies about me, this would still be a lie: Boudewijn = "Female" AND age=20 are two lies, still .F. (0).
0 1 0 1 1 0 0 1
(= decimal 13)
Either one is .T. will return a value of .T. (1). If both are false, this would return a logical false (0 -> 3rd column).
0 1 0 1 1 0 0 1
(= decimal 12)
Only if one of the two values is a true value (1), a .T. (1) is returned. In all other cases a .F. is returned (0).
Moving the bits a bit
Some other functions to manipulate bits are the itclear, bitRshift, bitLshift and bitset. In these functions it occurs that counting positions in bits starts at position zero. So the rightmost bit is position 0 (zero), the one next to that is position 1 et cetera. The leftmost position is bit 7. This is inconsistent with the other functions in VFP where counting normally starts at position 1. So at the end of this article I give some rewritten function for this kind of bit manipulation. OK, lets do a right shift first. We take a number and move all the bits 1 position to the right BITRshift(5,1).
0 1 0 1 BITRshift(5,1)
Result: decimal 2. Every bit in the upper row is shifted one position to the right. The leftmost bit is newly inserted. BITLshift() works into the other direction:
0 1 0 1 BITLshift(5,1)
Result: decimal 10. Every in the upper row is shifted one position to the left. The rightmost bit is newly inserted.
BitClear() clears a bit (makes it zero). This is one of the functions that starts counting at 0. So BitClear(5,1) will not clear the first bit but the second right bit: 0101 resulting in 0101: this is still decimal 5. When you want to clear the 0 bit, this would not give the expected result. BitClear(5,0) would be: 0101 -> 0100 (decimal 4).
Some other function where one can check or set bits are bittest() and bitset(). Bittest tests the bit in a bitstring to be 1, if so the function return .T. otherwise it returns .F.
As we know 5 is represented by the 0 1 0 1 values
?bittest(5,0) would thus return a .T.
?bittest(5,1) would return a .F., the second right bit is 0, the test shows that this is not a 1...
BitSet() set a 0 bit to 1. So if I would type ?bitset(5,1) the 2nd right bit would be set to 1. The return value therefore would be 1+2+4=7.
ABOUT THE AUTHOR: BOUDEWIJN LUTGERINK
Programming is one of the many hobbies of Boudewijn. He has worked with computers since 1985 and is the author of two books from Sybex. He has a weblog at
Enter the code shown: