C# 将数组指针传递给从特定偏移量开始的函数

本文关键字:偏移量 开始 函数 数组 指针 | 更新日期: 2023-09-27 18:33:10

我正在将C++应用程序移植到 C#,并遇到了一些指针问题。

我试图实现的是传递带有偏移量的数组指针,以便传递的函数可以在数组的正确部分工作。我不想更改函数的签名来为偏移量添加额外的值。

因此,这是我想在 C# 中传递的C++代码的示例段:

void DoSomething( double p[] )
{
    p[0] = 0.4;
    p[1] = 0.4;
}
int main()
{
    double Vector[3];
    Vector[0] = 0.2;
    Vector[1] = 0.2;
    Vector[2] = 0.2;
    DoSomething( &Vector[1] );
}

我该怎么做?请记住,我无法通过偏移量?

[编辑]谢谢大家的回答。首先,我必须道歉:我在复制代码时犯了一个大错误。

我写了

DoSomething( Vector[1] );

在最后一行而不是

DoSomething( &Vector[1] );

此问题已得到纠正。

然后我意识到我对签名不是很清楚。

  • 我可以稍微更改函数的签名,但我不能添加任何参数

  • 我已经在使用"不安全"和"固定"关键字,所以它不会伤害我

  • 它不需要是高效的代码,因为这种移植旨在成为其他人为原型项目编写的算法的快速和脏实现。如果项目是"Ok go",则代码将被扔到垃圾箱中,并在C++ dll中重写。

  • 函数"DoSomething"实际上是其他一些函数的巢穴,它被设计为一个快速的数学工作,但遗憾的是,我没有关于自己编码的所有知识。这就是为什么我认为作者已经很好地设计了它的功能,因为它在世界范围内使用。

我会尝试塞尔维的建议,过几天我回来再来找你。

C# 将数组指针传递给从特定偏移量开始的函数

完全不可能不更改DoSomething的签名,但您可以避免需要同时传递数组及其并排偏移量。 您可以通过创建一个类来执行此操作,该类组成数组并跟踪偏移量:

public class ArrayReference<T> : IEnumerable<T>
{
    //you can keep these entirely private if you prefer
    public T[] Array { get; private set; }
    public int Offset { get; private set; }
    public ArrayReference(T[] array, int offset)
    {
        Array = array;
        Offset = offset;
    }
    public T this[int index]
    {
        get
        {
            return Array[index + Offset];
        }
        set
        {
            Array[index + Offset] = value;
        }
    }
    public int Length
    {
        get
        {
            return Array.Length - Offset;
        }
    }
    public IEnumerator<T> GetEnumerator()
    {
        for (int i = Offset; i < Array.Length; i++)
            yield return Array[i];
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public static ArrayReference<T> operator +(
        ArrayReference<T> reference, int offset)
    {
        return new ArrayReference<T>(reference.Array, reference.Offset + offset);
    }
    public static ArrayReference<T> operator -(
        ArrayReference<T> reference, int offset)
    {
        return new ArrayReference<T>(reference.Array, reference.Offset - offset);
    }
    public static implicit operator ArrayReference<T>(T[] array)
    {
        return new ArrayReference<T>(array, 0);
    }
    public static implicit operator T[](ArrayReference<T> reference)
    {
        return reference.ToArray();
    }
}

您可能需要根据自己的特定需求向其添加其他功能。 您可以根据需要/想要公开或多或尽可能少的底层数组功能。

这实际上不是你在 C# 中这样做的方式。

执行此操作的唯一方法是使用不安全的代码,即使这样,它也不会是一个好的实现,因为您的方法将不安全,并且您的数组必须fixed

fixed 关键字将阻止垃圾回收器将数组移动到内存中的其他位置,但它可能会导致内存分区,然后性能下降。

此外,即使设计使然,这也不是一件好事,因为您不知道方法中的数组边界。

但是,如果您真的想这样做,请使用枚举器。

在您的主要方法中:

double[] d = new double[3];
d[0] = 1.0;
d[1] = 2.0;
d[2] = 3.0;
IEnumerator<double> e = d.AsEnumerable().GetEnumerator();
e.MoveNext();
tryEnumerate(e);

然后是您的DoSomething方法:

static void DoSomething(IEnumerator<double> e)
{
    while(e.MoveNext())
        Console.WriteLine(e.Current.ToString());
}

代码更新为使用扩展方法显示链接。 您可以轻松地返回任何和所有更改并更新所需的任何内容。

List<double> Vector;
Vector.Add(0.2);
Vector.Add(0.2);
Vector.Add(0.2);
DoSomething(Vector.GetRange(index,count));

如果需要维护原始列表,请执行以下操作:

public static List<double> GetRange(static List<double> list, int index, int count){
     return list.GetRange(Index,Count);
}
public static List<double> DoSomething(static List<double> list){
     //do something here
}

像这样使用它:

OriginalList().GetRange(Index,Count).DoSomething();