显式结构布局上的未分配字段

时间:2017-02-22 12:13:55

标签: c# struct structlayout

我想生成一个C#sqrt基准测试,但是一些sqrt函数需要一个用于按位计算的联合。

我的工会被定义为:

[StructLayout(LayoutKind.Explicit)]
struct U
{
    [FieldOffset(0)]
    public int i;
    [FieldOffset(0)]
    public float x;
}

和下一个代码在u.i上生成一个未分配的字段错误:

U u;
u.x = x;
u.i = (1 << 29) + (u.i >> 1) - (1 << 22);

我知道u.i在分配了u.x时被分配了,所以可以在编译时忽略未分配的字段错误而没有明确的u.i分配吗?

1 个答案:

答案 0 :(得分:2)

FieldOffset是一个互操作功能,不会以任何方式影响托管代码。无法保证(或要求)管理方的结构的实际布局将i放在与x相同的内存中。只要在进行互操作时它被编组到相同的内存位置,那么两个完全独立的字段的布局就完全有效。您的计算机上的运行时特别是 与两个字段重叠的事实不是您应该依赖的事情,而只是性能优化,实现细节。

如果要执行此类非托管操作,请使用不安全的代码。这就是它的用途。不要滥用互操作功能。当然,不要期望它是便携式的。

float x = 42.0f;

(*(int*)((void*)&x)) // The value of `x` reinterpreted as an int

您的sqrt近似的完整示例可能如下所示:

unsafe void Main()
{
  sqrt(42).Dump(); // 6.625
  sqrt(9).Dump();  // 3.125
}

unsafe float sqrt(float x)
{
  int* pX = (int*)((void*)&x);

  *pX = (1 << 29) + (*pX >> 1) - (1 << 22);

  return x;
}