FieldOffset
主要是互操作功能;它告诉运行时在本机上下文中使用时应如何编组结构。在某些情况下(blittable 结构),它也会影响托管内存布局。应该注意的是,任何显式的结构布局都意味着代码不再是可移植的。这对您的代码可能是也可能不是问题。
重要的部分是编译器甚至不会尝试验证不安全的代码,而不是一些非常简单的启发式方法。它仍然看到两个字段,并且您从未分配过其中一个字段,因此您违反了struct
合同。这与使用指针算法访问字段没有太大区别。您犯了一个错误并忘记分配一个字段的可能性仍然比这明确地是您想要的要大得多。如果您真的想要,您可以在阅读该字段之前U u = new U();
进行赋值(或使用构造函数;C# 不是 C,通常非常好) 。
但是在您的情况下,无论如何都没有理由使用联合字段。如果您想执行这样的非托管操作,请使用不安全代码。这就是它的用途。不要滥用互操作功能。当然,无论您选择哪种方式,都不要期望它是便携的。
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;
}