![](/img/trans.png)
[英]What's the difference between Marshal.SizeOf(typeof(T)) and Marshal.SizeOf(default(T))?
[英]Marshal.SizeOf(typeof(IntPtr)) vs sizeof(IntPtr)
我知道Marshal.SizeOf()
和sizeof()
根本區別是什么。 但是對於IntPtr
,無論采用哪種CPU架構,它們都不會總是返回完全相同的東西嗎?
一方面,有原始類型:
| 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
)實例,內部托管布局和封送處理圖像之間在總大小和字段布局排序上都可能存在顯着差異。 即使對於所謂的格式化類 ,后者也是正確的。 [1]
實際上很少需要有關實際托管結構布局的信息,實際上.NET竭盡全力使它變得不可發現。 您也不能影響結構的內部布局,這就是為什么Marshal
層提供了專門聲明互操作所需的布局的原因。
這是一個需要了解結構的運行時內存映像的真實大小的用例:假設您將結構的托管數組用於某種存儲Blob概念,並且希望每個塊(即數組)都保持固定總分配大小,例如〜84,800字節-顯然,在這種情況下,它不屬於LOH范圍 。 您希望此存儲類是泛型類,並使用定義了“記錄”或表條目的任意ValueType
類型進行參數化。 為了確定可進入每個托管數組塊的結構數,您需要發現運行時給出的結構的真實大小,因此可以將84,800除以該值。
要更詳細地檢查封送處理與托管內部結構的布局,填充和大小之間可能存在的差異,請參閱我對“ 如何檢查結構消耗的字節數? ”的擴展回答。
[1.]“ 格式化的類是一種引用類型,其引用類型由StructLayoutAttribute屬性指定為LayoutKind.Explicit或LayoutKind.Sequential 。
https://msdn.microsoft.com/zh-CN/library/2zhzfk83(v=vs.110).aspx
首先,您為什么想知道? 如果您的代碼寫得很好,則無需假設返回什么sizeof
和Marshal.SizeOf
。 您是否將使用編組器來封送您的任何IntPtr
實例? 然后使用Marshal.SizeOf
。 您的變量是永遠不會離開托管世界的,還是您正在使用自定義編組? 然后使用sizeof
(或IntPtr.Size
因為它不需要unsafe
塊)。 無論哪種情況,您都不必擔心它們是否返回相同的值。 那是實際的答案。
繼續理論。 根據C#語言規范 ,為sizeof(IntPtr)
返回的值是“該類型的變量中的字節總數,包括任何填充”(因為IntPtr
是結構)。 但是,它也指出此值是“實現定義的”。 因此,如果您想獲取技術知識,則C#規范只是說“想出來”。
也就是說, IntPtr
的文檔清楚地表明,該類型在32位平台上是32位,在64位平台上是64位,而ECMA-335文檔指出IntPtr
是一種特殊的內置類型,它對應於native int
,因此我認為我們可以暫時得出結論:在聲稱遵循規范的任何實現上, sizeof(IntPtr)
是可預測的:32位平台上為4,64位平台上為8。 IntPtr.Size
是替代方法,它明確地記錄了這一點。
Marshal.SizeOf(typeof(IntPtr))
是另一種野獸。 除了“非托管類型的大小”外,它沒有確切記錄返回的內容。 在水下,它會調用CLR中的一些本地代碼,該代碼向TypeHelper
詢問該TypeHelper
的基礎類型。 對於IntPtr
,這將返回sizeof(void*)
(在C ++中),對於大多數C ++編譯器和平台,在32位平台上當然為4,在64位平台上則為8。
從理論上講, sizeof(IntPtr)
和Marshal.SizeOf(typeof(IntPtr))
可能有所不同。 但這通常不是您自己關心的事情,因為運行時和抖動(或AOT編譯器)的組合不使sizeof(IntPtr)
等於Marshal.SizeOf(typeof(IntPtr))
-否則運行時只會使自己的生活更加困難。 另一方面,正如我所指出的,通常也沒有任何理由使您需要依賴它們相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.