Hi there,
F'Up to comp.lang.c
#define SetBits(bits,pos) (((bits)[(pos) >> 3]) |= (1 << ((pos) &
7)))
do not introduce linebreaks in macros; better:
#define SetBits(bits,pos) (((bits)[(pos) >> 3]) |= \
(1 << ((pos) & 7)))
or
#define SetBits(bits,pos) \
(((bits)[(pos) >> 3]) |= (1 << ((pos) & 7)))
Let's "parse" it:
There is an assignment |=, i.e. we could also write
(((bits)[(pos) >> 3]) = ((bits)[(pos) >> 3]) | (1 << ((pos) & 7)))
Now, what does ((bits)[(pos) >> 3]) mean?
We can assume that (bits) is a pointer to a certain object
It is the object at the address
address of (bits) plus ( (pos)>>3 times the size of the object (bits)
points to )
(pos)>>3 means "take the binary representation of (pos) and shift it by
three to the right (i.e. throw away the last three binary digits and
fill three digits from the left).
(pos) must be of an unsigned type.
The lowest three bits of (pos) are not used here.
Right side of |:
(1<< ((pos) & 7) )
Take one in binary, that is still one and shift it to the left by
(pos) & 7, i.e. append (pos) & 7 zeros at the right and throw away
(pos) & 7 digits from the left.
(pos) & 7 means "set to zero all bits of (pos) for which the
corresponding bits of 7(decimal) are zero. 7(decimal) is 111(binary),
so we essentially consider only the lowest three bits of (pos) which
went unused before. That means we can shift left between 0 and 7 digits.
Let us assume that (bits) was a pointer to an array of unsigned chars
which consist of 8 bits and (pos) was an unsigned int, then we could
directly "address" an arbitrary bit. If (pos) = n, where n=8*i+j,
0<=j<8, then SetBits(bits,pos) sets the n'th bit, that is, the
j'th bit of the i'th byte from the start to be one.
So, you essentially can interpret (bits) as a binary number of arbitrary
length for which you can set an arbitrary digit to 1 by using
SetBits. This means you can save factor 8 compared with using
every element of your array as a binary digit. Then, you would
use (bits)[(pos)]=1 instead of SetBits(bits,pos).
If you have problems with the binary operators, we can eliminate some
of them:
#define SetBits(bits,pos) (((bits)[(pos)/8]) |=\
(1 << ((pos)%8)))
If CHAR_BIT is not 8, and you mainly want to have the maximum memory
save, then replace 8 by CHAR_BIT:
#define SetBits(bits,pos) (((bits)[(pos)/CHAR_BIT]) |=\
(1 << ((pos)%CHAR_BIT)))
By the way: You are only setting one bit here, so SetBit would
be a better name for the macro.
Cheers,
Michael