Question

I am allocating an array that is intentionally bigger than the result of BitConverter.GetBytes. My goal is to leave the last byte empty so that I can prevent this number from being seen as the two's compliment and have tempPosBytes2[

When I run BitConverter.GetBytes my array tempPosBytes2 seems to shrink.

uint positiveNumber = 4293967296;
byte[] tempPosBytes2 = new byte[tempPosBytes.Length + 1]; // four bytes plus one
tempPosBytes2 = BitConverter.GetBytes(positiveNumber);  // tempPositiveBytes2 is now 4 bytes!!

Question

What is going on under the covers, and how can I leave the trailing byte without copying the array?

I need this to work with BigInteger(byte[]) as in the following:

BigInteger positiveBigIntBAD2 = new BigInteger(tempPosBytes2); // Invalid
Was it helpful?

Solution

Your array isn't being shrunk, you have an entirely new array allocated inside BitConverter.GetBytes.

Of course you can copy that output data into an array with size of your choice.

Or, just make your own version of BitConverter. It's really simple:

byte[] tempPosBytes2 = new byte[] { (byte)(positiveNumber), 
                                    (byte)(positiveNumber >> 8), 
                                    (byte)(positiveNumber >> 16), 
                                    (byte)(positiveNumber >> 24), 
                                    0 };

I suggest you compare the performance using both techniques.

BTW, you could just use the BigInteger constructor that takes a uint.

OTHER TIPS

It's not shrinking anything. GetBytes allocates a new array, always, and your assignment overwrites the reference to your existing byte array.

If you need the highest byte to always be zero, so that BigInteger doesn't interpret it as a negative number, then you can do Array.Resize after GetBytes to increase the size by 1, and the new byte will have the value zero, like you want.

There's an example on the BigInteger constructor page that talks about this very thing, and it provides an example that will result in only resizing the array when necessary. You could write yourself a helper method CreateUnsignedBigInteger(byte[]) which would do that very thing.

public BigInteger CreateUnsignedBigInteger(byte[] bytes)
{
    if ((bytes[bytes.Length - 1] & 0x80) > 0) 
    {
        byte[] old = bytes;
        bytes = new byte[old.Length + 1];
        Array.Copy(old, bytes, old.Length);
    }

    return new BigInteger(bytes);
}

BitConverter.GetBytes is not using your array, it cannot because you never passed it in.

Instead what is happening is you are creating an array, and then immediately destroying it.

If you need the result of GetBytes to be in your array, you can see if there is an overload or other method that takes in an array to write to, or copy the content yourself.

Ironically enough, if you want a byte[] that you can pass into a BigInteger constructor to give a value equivalent to your uint, you can do

byte[] tempPosBytes = new BigInteger(positiveNumber).ToByteArray();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top