C# BitConverter

Missing the flexibility of C/C++ way in interpreting bits? In C/C++, you can reinterpret the bits by simply casting it. For example if you have an int and you want to reinterpret it as float, you can do the following:
int   i = 1234;
float f = *( (float*) &i );
The question is how can we do this in C#? It turns out there's a class in C# to do this. Meet BitConverter class.
int   i = 1234;
float f = BitConverter.ToSingle( BitConverter.GetBytes(i), 0 );
With this class, you can reinterpret bits from primitive data types. Which should be enough. The only problem is that the class is not suitable to be called every frames. Why? Using Reflector.NET, you can easily tell that BitConverter.GetBytes() is actually allocating memory!
public static unsafe byte[] GetBytes(int value)
{
    byte[] buffer = new byte[4];
    fixed (byte* numRef = buffer)
    {
        *((int*) numRef) = value;
    }
    return buffer;
}
One solution is just to keep in mind not to call this every frame. If you are willing to compile your C# project with /unsafe option, you can actually do this:
public static unsafe float Int32BitsToSingle(int value)
{
    return *(((float*)&value));
}
The solution above (and including the C/C++ solution) is actually not a cross-platform solution. If you are writing XNA game for Xbox 360, you might already know that Xbox360 uses big endian and Intel PC uses little endian. You might actually screw things up!

I think the best solution is to write a class that mimic GetBytes() in BitConverter, but make sure we don't allocate memory. Here's my solution to the problem:
using System;

namespace CastTest
{
    public static class Cast
    {
        private static byte[] tempBuffer = new byte[8];

        public static unsafe void GetBytesTo(int value, byte[] buffer)
        {
            fixed (byte* numRef = buffer)
                *((int*)numRef) = value;
        }

        public static float ReinterpretToSingle(int value)
        {
            GetBytesTo(value, tempBuffer);
            return BitConverter.ToSingle(tempBuffer, 0);
        }
    }
}

Comments

Popular posts from this blog

GDC 2015 Links

D3D11 Compute Shader - Part 1

Mapping Square Texture to Trapezoid / Quadrilateral