![]() |
1
31
无论如何,使用该函数的一个好方法是使用一个泛型方法或扩展方法,如下所示:
|
![]() |
2
111
很长一段时间以来,结构一直是计算机工程中的麻烦动物。它们的内存布局非常依赖于硬件。为了提高效率,它们的成员必须对齐,这样CPU就可以快速地读写它们的值,而不必对字节进行多路复用以适应内存总线的宽度。每个编译器都有自己的成员打包策略,通常是由C或C++程序中的“γ-PrimaMax包”指令来指导的。 这没关系,但在互操作场景中是个问题。其中一段代码可能对结构布局做出不同的假设,而另一段代码则由不同的编译器编译。您可以在COM.NET的互操作编程解决方案中看到这一点。COM有 非常 对处理结构的支持较差。它不支持将它们作为本机自动化类型,但通过IRecordInfo接口有一个解决方法。它允许程序在运行时通过类型库中结构的显式声明来发现内存布局。它工作正常,但效率很低。 NET的设计者们做出了一个非常勇敢、正确的决定来解决这个问题。他们使结构的内存布局完全不可发现。没有文档化的方法来检索成员的偏移量。扩展一下,没有办法发现结构的大小。大家最喜欢的答案是使用Marshal.SizeOf()实际上并不是解决方案。返回struct的大小 在它被编组之后 ,在调用Marshal.StructureToPtr之前,需要传递给Marshal.allocTaskMem()的大小。它根据与结构关联的[StructLayout]属性排列和对齐结构成员。注意,这个属性对于结构不是必需的(就像对于类一样),运行时实现了一个默认的属性,它使用成员声明的顺序。 较小 错误的 对于结构大小,它返回的值太大。 长话短说,没有通用的方法可以通过编程获得结构大小的准确值。最好不要问这个问题。SizeOf()会给你一个猜测,假设结构是blittable的。如果出于某种原因需要准确的值,那么可以查看声明结构类型的局部变量的方法的生成的机器代码,并将其与没有该局部变量的相同方法进行比较。您将看到堆栈指针调整的不同之处,即方法顶部的“sub esp,xxx”指令。当然,它将依赖于体系结构,您通常会在64位模式下获得更大的结构。 |
![]() |
3
9
你可以用
|
![]() |
4
7
CIL
.NET
的汇编语言)来公开一些在C#中不可用的简洁功能。我打破了
它与
无论如何,您可以下载BSD许可库(和CIL) from BitBucket . 您还可以看到一些示例代码和更多细节 at my blog . |
![]() |
5
6
2减去托管指针:
三。显示托管内部结构布局:
4结果与讨论
运行上述程序的结果表明,该方法是可行的
如前所述,我们发现每个架构(
x86个
,
x64个
管理字段布局
在这个表中最重要的是要注意,(如
mentioned by Hans
进一步的重新排序优化了字段顺序,以便共享内部多余的填充,否则这些填充将被浪费。我们可以看到这个
当然,通过对上一个表的行进行排序,我们可以揭示一个表的真正内部托管布局
前面我们通过计算相邻实例之间的字节偏移量差来确定单个托管结构实例的大小。考虑到这一点,上一个表的最后几行显示了
清除
|
![]() |
6
4
.NET Core
,的
|
![]() |
7
3
你想用 System.Runtime.InteropServices.Marshal.SizeOf() :
|
![]() |
8
2
|
![]() |
Bfyuvf · 直接输入二进制可能的C++[重复] 3 年前 |
![]() |
Rado Harutyunyan · 在缓冲区节点中写入位 7 年前 |
![]() |
zaozaoer · >>java中带负字节值的and>>>运算符 7 年前 |
![]() |
rubyquartz · 交换无符号短整数的字节 7 年前 |
![]() |
DenoDev · C-十六进制输出中缺少0 7 年前 |