2012-02-10 8 views
3

2つの値の型からなる単純な構造体を作成しました。値型のみを含むカスタム構造体でMarshal.SizeOf()メソッドを使用

public struct Identifier 
{ 
    public Guid ID { get; set; } 
    public Byte RequestType { get; set; } 
} 

は、それから私は、次の文を使用して、カスタム構造体IdentifierMarshal.SizeOf()メソッドを呼び出しました。

なぜMarshal.SizeOf()が17を返さないのですか? 次の命令は、Guidオブジェクトが16バイトで、バイトobjectが1バイトであることを示しています。アライメントの理由からアンマネージメモリにコピーしたときに

Guid g = Guid.NewGuid(); 
Console.WriteLine(Marshal.SizeOf(g)); // output: 16 
Console.WriteLine(Marshal.SizeOf(g.GetType())); // output: 16 

Byte t = 0; 
Console.WriteLine(Marshal.SizeOf(t)); // output: 1 
Console.WriteLine(Marshal.SizeOf(t.GetType())); // output: 1 

答えて

6

デフォルトでは、CLRは再配置することができません(シンプルな構造体では使用できません)。これは、通常、メモリ内でワード境界に整列させたままにします。あなたはこの動作を好きで、それを変更したくない場合は、次のよう

は、あなたは何のパッキングを指定することはできません。

[StructLayout(LayoutKind.Sequential,Pack=1)] 
+4

構造体をメモリに配置するのはコンパイラではなく、CLRです。また、Marshal.SizeOfは、CLRによって整理された管理対象メモリのサイズではなく、アンマネージメモリ*にマーシャリングした後のサイズ*を返します。 – dtb

+0

なぜメモリ内にあるときに構造体をワード境界に整列させたままにしたいのですか?パディングを無効にする結果は何ですか? – enzom83

+1

@ enzom83: 'Identifier'の配列を持っていて、2番目の' Guid'にアクセスしたいとしたら、バイト整列ではないので、多段階読み込み(最初の単語の読み込み、2番目の単語の読み込み、所望のビットを組み合わせる)。 'StructLayout'を提供しないことによって、CLRにこれらの種類の詳細があなたにとって重要ではないことを伝えています。 – Guvante

3

あなたIdentifier構造体は、3つのバイトで埋められています。

+0

私は(例えば4バイト 'int')上に新しいフィールドを追加した場合、私のカスタム構造体では、Marshal.SizeOf()から24を取得します。したがって、 'Identifier'は常に3バイトで埋められているようです。実際、私のカスタム構造体にフィールドしかない場合、サイズは_correct_です。 – enzom83

+1

パディングが追加された場所と場所によってフィールドによって異なります。 1バイトが必ず3バイトで埋められるとは限りません。 – dtb

+1

@enzom83:たとえば、最初の*の横に* 2番目の*フィールドを追加した場合、パディングが1バイト下がります。 –

関連する問題