将 C++ 指针数学转换为 C#

Converting C++ Pointer Math to C#

我目前正在从事一个需要将一些 C++ 代码转换为 C# 环境的项目。在大多数情况下,它实际上非常简单,但我目前正在将一些较低级别的内存操作函数和 运行 转换为一些关于如何进行的不确定性。

在 C++ 代码中,我有很多这样的实例(显然非常简单):

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...
} 

我认为在 C# 中,我基本上必须将 "unsigned char*" 视为字节数组 (byte[])。但是要执行与指针运算类似的操作,本质上只是增加一个 "currentIndex" 值来访问字节数组吗?对于像 AnotherFunc 这样的东西,我想这意味着我还需要传入一个起始索引,如果起始索引不是 0?

只是想确认这是在 C# 中应该如何完成的,或者是否有更好的方法来进行这种转换。另外,在我现在的环境下不能使用"unsafe"关键字,所以实际使用指针是不可能的!

C# 取消指针的确切原因是防止指针运算(更确切地说,指针运算容易出错)。

一般来说,任何由指针和内存偏移量引用的 C++ 内存块在 C# 中确实最好转换为数组(因此即使 C# 数组也以 [0] 开头)。但是,您应该将数组保留为与基础数据相同的类型 -char[] 而不是 byte[]。因为这也是一个char[],你应该看看这个函数的整体用途是什么,考虑换成一个string.

这两个函数将 myMemoryBlock 视为一个数组。您可以将单个 myMemoryBlock 参数替换为一对 myArraymyOffset,如下所示:

void SomeFunc(char[] myArray)
{
    AnotherFunc(myArray, 0);

    AnotherFunc(myArray, memoryOffset);
}

void AnotherFunc(char[] data, int offset)
{
    // Also simplified - basically, modifying the
    // byte pointed to by data and then increasing to the next item.
    data[offset++] = 2;
    data[offset++] = 5;
    // And so on...
}

注意: C++ 类型 unsigned char 通常用作 "untyped block of memory" 的替代(相对于 "a block of memory representing character data")。如果您的情况是这种情况,即指针指向不一定是字符的内存,则 byte 数组将是更合适的选择。

正如@dasblinkenlight所说,C#(和Java)处理指向内存数据块(通常是字节或字符数组)的任意指针的方法是添加一个额外的offset 访问数据块的方法的参数。

添加第三个 length 参数也很常见。因此,传递一块内存的方法 Foo() 的一般形式是:

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

您在 C# 库中随处可见。对于在两个内存块上操作的方法(例如,将一个块复制到另一个块,或将一个块与另一个块进行比较等)的另一种常见形式是:

// 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)
{ ... }

对于期望对整个内存块(数组)进行操作的方法,这些方法通常如下所示:

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