gpt4 book ai didi

c# - LayoutKind.explicit 对于本身就是结构的字段的 .NET 行为

转载 作者:行者123 更新时间:2023-11-30 20:59:39 31 4
gpt4 key购买 nike

问题

我尝试使用 [StructLayout(LayoutKind.Explicit)] 构建一个结构 (SA),它有一个字段是另一个 struct (SB).

首先:我很惊讶我被允许在没有[StructLayout(LayoutKind.Explicit)]的情况下声明其他结构,而在SA中,所有字段必须[FieldOffset(0)],否则编译器会大喊大叫。这没有多大意义。

  • 这是编译器警告/错误中的漏洞吗?

其次:好像把SB中的所有引用(object)字段都移到了SB的前面>.

  • 是否在任何地方描述了这种行为?
  • 是否依赖于实现?
  • 它是否在依赖于实现的任何地方定义? :)

注意:我不打算在生产代码中使用它。我问这个问题主要是出于好奇。

实验

// No object fields in SB
// Gives the following layout (deduced from experimentation with the C# debugger):

// | f0 | f4 and i | f8 and j | f12 and k | f16 |

[StructLayout(LayoutKind.Explicit)]
struct SA {
[FieldOffset(0)] int f0;
[FieldOffset(4)] SB sb;
[FieldOffset(4)] int f4;
[FieldOffset(8)] int f8;
[FieldOffset(12)] int f12;
[FieldOffset(16)] int f16;
}
struct SB { int i; int j; int k; }

// One object field in SB
// Gives the following layout:

// | f0 | f4 and o1 | f8 and i | f12 and j | f16 and k |

// If I add an `object` field after `j` in `SB`, i *have* to convert
// `f4` to `object`, otherwise I get a `TypeLoadException`.
// No other field will do.

[StructLayout(LayoutKind.Explicit)]
struct SA {
[FieldOffset(0)] int f0;
[FieldOffset(4)] SB sb;
[FieldOffset(4)] object f4;
[FieldOffset(8)] int f8;
[FieldOffset(12)] int f12;
[FieldOffset(16)] int f16;
}
struct SB { int i; int j; object o1; int k; }

// Two `object` fields in `SB`
// Gives the following layout:

// | f0 | f4 and o1 | f8 and o2 | f12 and i | f16 and j | k |

// If I add another `object` field after the first one in `SB`, i *have* to convert
// `f8` to `object`, otherwise I get a `TypeLoadException`.
// No other field will do.

[StructLayout(LayoutKind.Explicit)]
struct SA {
[FieldOffset(0)] int f0;
[FieldOffset(4)] SB sb;
[FieldOffset(4)] object f4;
[FieldOffset(8)] object f8;
[FieldOffset(12)] int f12;
[FieldOffset(16)] int f16;
}
struct SB { int i; int j; object o1; object o2; int k; }

最佳答案

Is this a loophole in the compiler's warnings/errors ?

不,没有错。允许字段重叠,这就是 LayoutKind.Explicit 首先存在的原因。它允许在非托管代码中声明与 union 等效的内容,而在 C# 中不支持。你不能突然停止在结构声明中使用 [FieldOffset],运行时坚持你在结构的所有成员上使用它。这在技术上不是必需的,而是一个避免错误假设的简单要求。

it seems that all reference (object) fields in SB are moved

是的,这是正常的。 CLR 以未记录和不可发现的方式布置对象。它使用的确切规则没有记录并且可能会更改。它也不会因不同的抖动而重复。在对象被编码、Marshal.StructureToPtr() 调用或由 pinvoke 编码程序隐式地进行之前,布局不会变得可预测。这是唯一一次确切的布局很重要。我在 this answer 中写过这种行为的基本原理。 .

关于c# - LayoutKind.explicit 对于本身就是结构的字段的 .NET 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15392054/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com