Search code examples
c#c++arrayspointerspointer-arithmetic

Converting C++ Pointer Math to C#


I'm currently working on a project that requires converting some C++ code to a C# environment. For the most part, it's actually pretty straightforward, but I'm currently converting some lower-level memory manipulation functions and running into some uncertainty as to how to proceed.

In the C++ code, I've got a lot of instances of things like this (obviously quite simplified):

void SomeFunc(unsigned char* myMemoryBlock)
{
    AnotherFunc(myMemoryBlock);

    AnotherFunc(myMemoryBlock + memoryOffset);
}

void AnotherFunc(unsigned char* data)
{
    // Also simplified - basically, modifying the
    // byte pointed to by data and then increasing to the next item.
    *data = 2;
    data++;

    *data = 5;
    data++;

    // And so on...
} 

I'm thinking that in C#, I've basically got to treat the "unsigned char*" as a byte array (byte[]). But to perform a similar operation to the pointer arithmetic, is that essentially just increasing a "currentIndex" value for accessing the byte array? For something like AnotherFunc, I guess that means I'd also need to pass in a starting index, if the starting index isn't 0?

Just want to confirm this is how it should be done in C#, or if there's a better way to make that sort of conversion. Also, I can't use the "unsafe" keyword in my current environment, so actually using pointers is not possible!


Solution

  • Just like @dasblinkenlight said, the C# (and Java) way to deal with arbitrary pointers to memory data blocks (which are usually byte or char arrays) is to add an additional offset parameter to the methods that access the data blocks.

    It is also common to add a third length parameter. Thus the general form for a method Foo() that is passed a block of memory is:

    // Operate on 'block', starting at index 'offset',
    // for 'length' elements
    //
    int Foo(byte[] block, int offset, int length)
    { ... }
    

    You see this all over the place in the C# library. Another form that is common for methods that operate on two memory blocks (e.g., copying one block to another, or comparing one block to another, etc.) is this:

    // Operate on blocks 'src' starting at index 'srcOff',
    // and on block 'dst' starting at 'dstOff',
    // for a total of 'length' elements
    //
    int Bar(byte[] src, int srcOff, byte[] dst, int dstOff, int length)
    { ... }
    

    For methods that expect to operate on an entire memory block (array), these generally look like this:

    // Overloaded version of Foo() that
    // operates on the entire array 'block'
    //
    int Foo(byte[] block)
    {
        return Foo(block, 0, block.Length);
    }