获取指向struct内部的指针(不安全的上下文)

Ale*_*aev 5 c# struct pointers unsafe

长话短说,我将提供一个简单的例子,它可能有用:

public struct Vector3f {
    public float x;
    public float y;
    public float z;

    public unsafe float this[int index] {
        get {
            // Get "p" somehow, so that it points to "this"...

            return p[index];
        }

        set {
            // Get "p" somehow, so that it points to "this"...

            p[index] = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我猜你有我的观点:

var v = new Vector3f();

Assert(v.x == v[0]);
Run Code Online (Sandbox Code Playgroud)

编辑1:

对于那些仍然问:)

Assert(v.y == v[1]);
Assert(v.z == v[2]);
Run Code Online (Sandbox Code Playgroud)

编辑2:

这会fixed产生多余的开销吗?或者这个结构可能已经修复,因此fixed在这里没有效果,只需要满足编译器的需要?可能的答案.

Eri*_*ert 8

首先,我不会为此使用不安全的代码,除非我首先确定(1)带有开关的明显代码将是整个程序中最慢的代码并导致显着的,用户可观察到的减速,并且(2)继续不安全的代码修复了性能问题.

其次,如果我使用不安全的代码,那么对结构包装做出假设是非常危险的.CLR在如何选择打包结构方面具有广泛的优势.如果你要做这个危险的事情那么你应该使用struct layout属性来确保浮动正好在你需要的位置.

第三,是什么阻止了一个错误的调用者传递否定索引或过大的索引?

第四:

修复是否会在此处创建冗余开销

我不知道"冗余开销"意味着什么."fixed"使得抖动告诉垃圾收集器"不要移动这个东西,因为我需要对它进行指针运算".你正在修理一段时间,这是理想的; 长时间固定使得集合更容易被弄乱,因为无法移动固定存储.

第五:

或者这个结构可能已经修复,因此修复在这里没有效果,只需满足编译器需要?

也许!也许"this"引用的变量已经是固定变量.也许不是.编译器如何知道结构的"this"是否是对固定存储的引用?我们必须假设最坏的情况,因此您需要修复它.

  • @Haroogan你担心与"固定"相关的成本,但是仍然不清楚为什么你需要在这里使用不安全的代码.为什么不直接让`struct`成为一个数组呢?或者在索引器中使用`switch`语句?或者将索引支持的`X`,`Y`和`Z`属性变成`private`数组?这些听起来都是更好的选择. (6认同)
  • @ordag:我不知道 - 是吗?C#规范声明"成员被打包到结构中的顺序是未指定的.出于对齐目的,在结构的开头,结构内部和结构的末尾可能有未命名的填充." 您无法保证*结构以任何特定方式包装.如果你*发生的某些实现只是用**以你喜欢的方式打包结构,那就是你的好运.你想在多大程度上相信运气? (4认同)
  • @ordag:某些版本的运行时或C#编译器的某些实现可能会对您做出保证.我的观点是,保证不是由C#语言*制作的.是否由Mono提供同样的保证?通过紧凑的框架?通过一些未来的实施?我不愿意做出这些假设,但是我的观点因为多年来调查由人造成的神秘错误而变得有色 - 其中一些人是我自己的过去版本 - 他们对结构布局的实现细节做出了无根据的假设.结果被违反的假设. (3认同)

ord*_*dag 5

你的意思是这样的?

get
{
    // (index validation omitted)
    fixed (Vector3f* thisPtr = &this)
    {
        return ((float*)thisPtr)[index];
    }
}
Run Code Online (Sandbox Code Playgroud)