我知道Marshal.SizeOf()
和sizeof()
的根本区别如何。但是在IntPtr
的情况下,无论CPU架构如何,它们都不会总是返回完全相同的东西吗?
答案 0 :(得分:1)
首先,你为什么想知道?如果您的代码编写得很好,那么您就不需要对sizeof
和Marshal.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.Explicit或LayoutKind.Sequential。”
<子> https://msdn.microsoft.com/en-us/library/2zhzfk83(v=vs.110).aspx 子>