假设我有一个这样定义的结构:
[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 个双精度向量而不是 4 个浮点数的向量的指令,但这没有实际区别),因此不会导致任何异常错位。我找不到关于以这种方式加载 Vector4
官方需要什么样的对齐方式的明确文档。