Question

Please consider this (non-homework) exercise of converting a slash-notation (e.g. 24, 30) to a subnet mask.

When I copy a BitArray to byte[], the internal ordering of the BitArray leads to incorrect output.

For instance, with an input of numberOfSetBits=24, ToString() should return 255.255.255.0 (this works because the bits are symmetrical). However, an input of 30 results in 255.255.255.63 instead of the expected 255.255.255.252. Yes, I realize that that's just the way a BitArray handles it's children (there's an old discussion about the issue, unfortunately without a solution, just a never-ending argument over why one ordering would be better).

But how, for the love of god, can I get this code to treat 1111 1100 (=252) for what it is instead of mangling it to 0011 1111 (=63)? I believe I'll have to change the order in which I'm adding the bits in the first place, but I can't get it to work.

public class SubnetMask
{
    private byte[] parts = new byte[4];

    public static SubnetMask FromSlash(int numberOfSetBits)
    {
        BitArray bits = new BitArray(32);
        for (int i = 0; i < numberOfSetBits; i++)
        {
            bits[i] = true;
        }
        return new SubnetMask(bits);
    }

    private SubnetMask(BitArray bits)
    {
        bits.CopyTo(parts, 0);
    }

    public override string ToString()
    {
        return string.Join(".", parts);
    }
}

Thank you.

Was it helpful?

Solution

You don't need a BitArray, you can create the mask from shifting an integer, and use BitConverter.GetBytes to get it as bytes:

public static SubnetMask FromSlash(int numberOfSetBits) {
  int mask = numberOfSetBits == 0 ? 0 : -1 << (32 - numberOfSetBits);
  byte[] bits = BitConverter.GetBytes(mask);
  if (BitConverter.IsLittleEndian) Array.Reverse(bits);
  return new SubnetMask(bits);
}

OTHER TIPS

Wouldn't this just be fixed by doing:

int bitPlace = 32;
for (int i = 0; i < numberOfSetBits; i++)
{
    bits[--bitPlace] = true;
}

This sets the high-order bits (rather than the low-order bits). The reasoning here is precisely what is mentioned in the answer you linked- BitArray stores the least-significant digits in the lowest index, so the bit array 11111000000000 below is [indexed] thus:

(Most Significant)                  (Least Significant)
 1    1    1    1    1   0   0   0   0   0   0   0   0   0
[14] [13] [11] [10] [9] [8] [7] [6] [5] [4] [3] [2] [1] [0]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top