Marshal.SizeOf(typeof(IntPtr))vs sizeof(IntPtr)

时间:2017-01-04 11:03:17

标签: c# .net

我知道Marshal.SizeOf()sizeof()的根本区别如何。但是在IntPtr的情况下,无论CPU架构如何,它们都不会总是返回完全相同的东西吗?

2 个答案:

答案 0 :(得分:1)

首先,你为什么想知道?如果您的代码编写得很好,那么您就不需要对sizeofMarshal.SizeOf返回的内容做任何假设。您是否会使用编组人员来编组任何IntPtr个实例?然后使用Marshal.SizeOf。您的变量是否永远不会离开托管世界,或者您是否使用自定义编组?然后使用sizeof(或IntPtr.Size,因为它不需要unsafe块。在这两种情况下,您都不关心它们是否返回相同的值。这是实际的答案。

关于理论。根据{{​​3}},sizeof(IntPtr)返回的值是"该类型变量中的总字节数,包括任何填充" (因为IntPtr是一个结构)。但是,它也注意到这个值是"实现定义"。所以,如果你想获得技术,C#规范只是说"弄清楚"。

也就是说,IntPtr的文档清楚地表明该类型在32位平台上是32位,在64位平台上是64位,而C# language specification文档是IntPtr }}是一个与native int对应的特殊内置类型,因此我认为我们可以暂时得出结论:sizeof(IntPtr)可以预测任何声称遵循规范的实现:4在32位平台上,在64位平台上有8个。 IntPtr.Size是另一种选择,它明确地记录了这一点。

Marshal.SizeOf(typeof(IntPtr))是一个不同的野兽。除了"非托管类型的大小之外,它没有准确记录它将返回的内容&#34 ;;在水下,它在CLR中调用一些本机代码,询问TypeHelper大小的基础类型。对于IntPtr,这将返回sizeof(void*)(在C ++中),当然,对于绝大多数C ++编译器和平台,它在32位平台上为4,在64位平台上为8。 / p>

从理论上讲,sizeof(IntPtr)Marshal.SizeOf(typeof(IntPtr))在技术上可能不同。但这并不是你一般关心的事情,因为运行时和抖动(或AOT编译器)的组合使sizeof(IntPtr)等于{{1}是不明智的。 - 否则运行时只会使自己的生活变得更加困难。另一方面,正如我所指出的那样,通常没有任何理由说明为什么你需要依赖它们是相同的。

答案 1 :(得分:1)

首先,有原始类型:

  

| x64 | x86
   | Marshal. | Marshal.
  Primitive | SizeOf<T>() sizeof(T) | SizeOf<T>() sizeof(T)
  ========= | =========== =========== | =========== ===========
   Boolean | 4 <-> 1 | 4 <-> 1
   Byte | 1 1 | 1 1
   SByte | 1 1 | 1 1
   Int16 | 2 2 | 2 2
   UInt16 | 2 2 | 2 2
   Int32 | 4 4 | 4 4
   UInt32 | 4 4 | 4 4
   Int64 | 8 8 | 8 8
   UInt64 | 8 8 | 8 8
   IntPtr | 8 8 <-> 4 4
   UIntPtr | 8 8 <-> 4 4
   Char | 1 <-> 2 | 1 <-> 2
   Double | 8 8 | 8 8
   Single | 4 4 | 4 4

除此之外,对于 .NET 中的struct(ValueType)实例,内部托管布局和编组图像之间可能存在显着差异,包括总大小和字段布局排序。即使对于所谓的formatted classes [1]

,后者也是如此

实际上需要有关实际托管结构布局的信息是很少见的,事实上 .NET 在尝试使其无法发现方面付出了很大的努力。您也无法影响结构的内部布局,这正是Marshal图层提供专门声明互操作所需布局的能力的原因。

这是一个需要知道结构的运行时内存映像的真实大小的用例:假设您正在使用托管阵列结构来存储某种存储blob概念,并且您希望每个块(数组,即)都保持不变在固定的总分配大小下,比如说~84,800字节 - 显然在这种情况下不会超出LOH。您希望此存储类是泛型类,使用任意ValueType类型进行参数化,该类型定义“记录”或表条目。要确定可以进入每个托管数组块的结构数,您需要发现在运行时给出的结构的真实大小,因此可以将84,800除以该值。

有关 编组 托管内部 结构布局之间可能出现的差异的更详细检查,填充和大小,请参阅我对“How do I check the number of bytes consumed by a structure?

的扩展答案


[1。]“格式化的类是一种引用类型,其布局由StructLayoutAttribute属性指定为LayoutKind.ExplicitLayoutKind.Sequential。”
<子> https://msdn.microsoft.com/en-us/library/2zhzfk83(v=vs.110).aspx

相关问题