Reputation: 3406
I've tried really hard, but I can't seem to understand what's going on in this code. Can anyone please shed some light?
public class BitArrary
{
private Byte[] m_byteArray;
private Int32 m_numBits;
public BitArrary(Int32 numBits)
{
if (numBits <= 0)
throw new ArgumentOutOfRangeException("Must be greater then 0");
m_numBits = numBits;
m_byteArray = new Byte[(numBits + 7) / 8];
}
public Boolean this[Int32 bitPos]
{
get
{
if ((bitPos < 0) || (bitPos >= m_numBits))
{
throw new ArgumentOutOfRangeException("bitPos");
}
else
{
return (m_byteArray[bitPos / 8] & (1 << (bitPos % 8))) != 0;
}
}
set
{
if ((bitPos < 0) || (bitPos > m_numBits))
throw new ArgumentOutOfRangeException("bitPos");
if (value)
{
m_byteArray[bitPos / 8] = (Byte)(m_byteArray[bitPos / 8] | (1 << (bitPos % 8)));
}
else
{
m_byteArray[bitPos / 8] = (Byte)(m_byteArray[bitPos / 8] & ~(1 << (bitPos % 8)));
}
}
}
}
I don't get the parts (the three lines) where there is operation on bits. As far as I get it, in first one, its ANDing
the value of bit array to find if that bit is on. In second one, its ORing
, and in the third one ANDing
with NOT
, is that about right what I think is happening in these three lines?
Whats really hurting my brain in what is this doing 1 << (bitPos % 8)
? And what does ANDing
, ORing
or ANDing
with NOT
of it, is going to do? What I know is that you can left or right shit a value of something (or other, I am not really clear on this.) So what is this doing? is it shift 1
or what?
Can anyone please explain?
EDIT : Edited for full code...
Upvotes: 1
Views: 343
Reputation: 14002
Ok looks like the is a private field which contains the bytes (m_byteArray) and this gets a bit from the bytearray (I'm assuming that the bytearray is contiguous and this attempts to get the bits from a certain position - e.g. imagine there are 3 bytes, position 13 would get bit 5 from byte 2)
Edit: To summarise better
Image we have 3 bytes in the byte array
00101011 00101010 01000010
If we want bit 13 we would pass '12' to the indexer IMPORTANT TO REMEMBER!!
00101011 00101010 01000010
-------------^
(Remember it's 0 based)
We go
m_byteArray[12 / 8] (12 / 8 = 1 so we know we want byte number two at index 1 - byte array is also zero based!)
So we have the second byte (at index 1)
00101010
----^
Now we go
00101010 & (1 << (12 % 8))
Which is equivalent to
00101010 & 00000001 << 4
Which is
00101010 & 00001000
So this masks off to
1 & 1
Which returns 1 :)
For masks that end up as
1 & 0
Logically that returns 0
Upvotes: 2
Reputation: 144136
The line:
return (m_byteArray[bitPos / 8] & (1 << (bitPos % 8))) != 0;
returns whether the nth bit in a byte array is set.
bitPos / 8
finds the byte in which the indexed bit is in, and
1 << (bitPos % 8))
creates a bitmask for the associated byte.
As an example, if you wanted to find whether the 10th bit was set, bitPos
would be 9.
bitPos / 8
= 1, so the associated bit is in the second byte within the array.
bitPos % 8
= 1, so the expression (1 << (bitPos % 8)) creates a bitmask of 00000010
. Applying this mask to byteArray[1]
will return 1 if the second bit is set, or 0 otherwise.
The logic for the setters is similar, except that
m_byteArray[bitPos / 8] | (1 << (bitPos % 8))
will set the bit in the associated position, while
(m_byteArray[bitPos / 8] & ~(1 << (bitPos % 8))
will clear it.
Upvotes: 1