假设我有一个如下定义的结构:
[StructLayout(LayoutKind.Explicit, Size = 16, Pack = 1)]
readonly struct Example {
[FieldOffset(0)]
public float A;
[FieldOffset(4)]
public float B;
[FieldOffset(8)]
public float C;
[FieldOffset(12)]
public float D;
}
Example
的本地实例和参数实例是否保证 16 字节对齐?
具体来说,我很好奇是否可以使用 Unsafe.As
将这样的结构重新解释为 Vector4
:
static void Test(Example e) {
var vec4 = Unsafe.As<Example, Vector4>(ref e); // Is vec4 aligned?
var e2 = new Example();
vec4 = Unsafe.As<Example, Vector4>(ref e2); // Is vec4 aligned?
}
最佳答案
结构类型的局部变量和参数不一定是“过度对齐”(即与标量代码所需的任何内容对齐)。 Example
不需要 16 对齐,因此 JIT 编译器没有特定的动机来确保它得到它,当然它可能会发生,我必须稍微修改一下源代码得到一个未对齐的地址(好吧,不是 16 对齐,从标量的角度来看它仍然足够对齐)。
下面是实际中实际未进行 16 对齐的屏幕截图:
为了实现这一点,我在 e
之前插入了另一个结构参数,其大小为 8。
之所以存在冗余移动,是因为这种情况发生在未优化模式下(模块加载时抑制 JIT 优化,这是调试的默认设置,但可以将其关闭以调试优化代码,这有其自身的问题)。
但是,显然,Unsafe.As
产生的负载是未对齐的负载(vmovupd
,理论上,这是加载 2 个 double 向量而不是 4 个 double 向量的指令) float ,但这没有实际区别),因此未对准不会导致异常。我找不到明确的文档来说明以这种方式加载 Vector4
需要哪种对齐方式。
关于c# - C# 结构体参数和局部变量默认对齐吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77062415/