Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# byte array to fixed int pointer

is it possible to somehow cast the type of a pointer created by the fixed() statement?

This is the situation:

I have an array of byte, which i would like to iterate through, however i would like the values to be treated as int, thus having an int* instead of a byte*.

Here's some exemplary code:

byte[] rawdata = new byte[1024];

fixed(int* ptr = rawdata) //this fails with an implicit cast error
{
    for(int i = idx; i < rawdata.Length; i++)
    {
        //do some work here
    }
}

Can this be done without having to do the cast inside the iteration?

like image 203
WhiteN01se Avatar asked Jan 17 '12 11:01

WhiteN01se


3 Answers

byte[] rawdata = new byte[1024];

fixed(byte* bptr = rawdata)
{
    int* ptr=(int*)bptr;
    for(int i = idx; i < rawdata.Length; i++)
    {
        //do some work here
    }
}
like image 136
Eugen Rieck Avatar answered Oct 07 '22 09:10

Eugen Rieck


I believe you have to go via a byte*. For example:

using System;

class Test
{
    unsafe static void Main()
    {
        byte[] rawData = new byte[1024];
        rawData[0] = 1;
        rawData[1] = 2;

        fixed (byte* bytePtr = rawData)
        {
            int* intPtr = (int*) bytePtr;
            Console.WriteLine(intPtr[0]); // Prints 513 on my box
        }
    }
}

Note that when iterating, you should use rawData.Length / 4, not rawData.Length if you're treating your byte array as a sequence of 32-bit values.

like image 26
Jon Skeet Avatar answered Oct 07 '22 07:10

Jon Skeet


I found a - seemingly - more elegant and for some reason also faster way of doing this:

        byte[] rawData = new byte[1024];
        GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
        int* iPtr = (int*)rawDataHandle.AddrOfPinnedObject().ToPointer();
        int length = rawData.Length / sizeof (int);

        for (int idx = 0; idx < length; idx++, iPtr++)
        {
            (*iPtr) = idx;
            Console.WriteLine("Value of integer at pointer position: {0}", (*iPtr));
        }
        rawDataHandle.Free();

This way the only thing i need to do - apart from setting the correct iteration length - is increment the pointer. I compared the code with the one using the fixed statement, and this one is slightly faster.

like image 39
WhiteN01se Avatar answered Oct 07 '22 09:10

WhiteN01se