20
|
Matthew Watson · 技术社区 · 14 年前 |
![]() |
1
16
它与
(surprising) fact that
样本输出: 64-bit: True Layout of OneField: Auto Layout of Composite: Sequential Size of Composite: 24 L: 48F050 M: 48F048 N: 48F058
如果我们从
64-bit: True Layout of OneField: Sequential Layout of Composite: Sequential Size of Composite: 24 L: 48F048 M: 48F050 N: 48F058 这些例子与 平台编译(因此大小为24,是8的3倍,这并不奇怪),但对于x86,我们看到的是相同的“无序”指针地址。
所以我想我可以断定
它不再试图保持顺序
当其中一个成员是
|
![]() |
2
6
仔细阅读布局规则的规范。 仅当对象在非托管内存中公开时,布局规则才控制布局 . 这意味着编译器可以随意放置字段,直到实际导出对象为止。令我有些惊讶的是,这甚至是固定布局! 做 说明此处选择的最终布局,但这与编译器忽略布局规范的原因无关。 包含 在那里!不是很明显! 是 这里推荐固定布局的各种注释通常是很好的建议,但在这种情况下,这并不一定有任何效果,因为包含DateTime字段可以免除编译器执行布局的责任。更糟的是:编译器不是 必修的 尊重布局,但它是 尊重布局。这意味着CLR的后续版本在这方面可以自由地有不同的行为。 在我看来,对布局的处理是CLI中的一个设计缺陷。当用户指定一个布局时,编译器不应该绕着它们走。最好把事情简单化,让编译器按要求去做。尤其是在布局方面。”我们都知道,“聪明”是一个四个字母的单词。 |
![]() |
3
3
问:“在使用COM DATETIME类型的C/C++结构互操作时,这种行为有什么影响吗?” 答:不,因为在使用封送处理时会考虑布局。(我根据经验证实了这一点。) 问题“有人能解释一下吗?”. 答:我仍然不确定这一点,但是由于没有定义结构的内部表示,编译器可以做它喜欢做的事情。 |
![]() |
4
2
几个因素
所以C编译器有一些未经文档化的规则,用来尝试获取 最好的 如果您需要知道结构的布局,那么您应该自己指定它,而不是让编译器来决定。 但是LayoutKind.Sequential确实会阻止编译器更改字段的顺序。 |
![]() |
5
2
它正确地封送到本机结构中的原因是,数据使用封送值设置的属性复制到本机内存中。 因此,管理结构的安排对原生结构的安排没有影响。只有属性才影响原生结构的排列。
|
![]() |
6
1
如果你要用C/C++来互操作,我会一直使用StuttDebug。我将使用Explicit而不是Sequential,并使用FieldOffset指定每个位置。另外,添加Pack变量。
包变量在C++代码中尤其重要,它可以编译在具有不同字大小的不同系统上。 我也会忽略使用不安全代码时可以看到的地址。只要封送处理正确,编译器做什么并不重要。 |