2017-12-25 11 views
1

2つのコードの結果を解釈する際に問題があります。StructLayoutAttribute.Packの混乱

using System; 
using System.Runtime.InteropServices; 

[StructLayout(LayoutKind.Sequential, Pack = 0)] 
struct MyStruct 
{ 
    public byte b1; 
    public char c2; 
    public int i3; 
} 

public class Example 
{ 
    public unsafe static void Main() 
    { 
     MyStruct myStruct = new MyStruct(); 
     byte* addr = (byte*)&myStruct;  
     Console.WriteLine("Size:  {0}", sizeof(MyStruct));  
     Console.WriteLine("b1 Offset: {0}", &myStruct.b1 - addr); 
     Console.WriteLine("c2 Offset: {0}", (byte*)&myStruct.c2 - addr); 
     Console.WriteLine("i3 Offset: {0}", (byte*)&myStruct.i3 - addr);  
     Console.ReadLine(); 
    } 
} 

私はpublic char c2;Console.WriteLine("c2 Offset: {0}", (byte*)&myStruct.c2 - addr)をコメントアウトした場合上記の結果は

Size :  8 

b1 Offset: 0 
c2 Offset: 2 
i3 Offset: 4 

である;、私は

Size :  8 

b1 Offset: 0 
i3 Offset: 4 

になるだろう今、私はデフォルトの2番目のシナリオを、説明できると思いますパッキングサイズは、パック= 0の場合のmyStructの最大要素サイズのサイズです。パディングの1バイト+ 3バイト+ 4バイト= 8です。

しかし、最初のシナリオでは同じことは考えられません。私の予想される結果は、(1バイト+ 3バイトのパディング)+(2バイトのchar + 2バイトのパディング)+(4バイトのint)です。したがって、合計サイズは4バイトのパッキングサイズ(intのサイズ)として12になり、それぞれのオフセットは0,4,8となります。

ここでは何が欠けていますか? (Xはあなたのタイプのアライメントである)X-バイトのチャンクであなたの構造体を読んで何かを考えることが役立つかもしれないアライメントを理解することが

おかげ

+0

ありがとうございました。しかし、デフォルトではPack = 0は使用されていませんか?私は、デフォルトでオブジェクト内の最大の要素のサイズを意味すると考えました。 –

+0

@HansPassantドキュメントによるとhttps://msdn.microsoft.com/de-de/library/system.runtime.interopservices.structlayoutattribute.pack(v=vs.110).aspxは「現在のデフォルトのパッキングサイズプラットフォーム "。 – ckuri

+0

@ckuri MSDNでもこう言及しています。型のデフォルトの配置は、最大の要素のサイズです。私はこれを非常に混乱させることがわかります。 –

答えて

1

。あなたの例ではXは4です。パディングが追加されない場合、最初の構造体(charを持つ)の最初の4バイトを読み取ると、バイト、char、次のintフィールドの1バイトが読み込まれます。これは、(部分的なフィールドバイトの読み込みを避ける)パディングが必要な理由です。問題を「修正」するには、1バイトのパディングが必要です。最初の4バイトの読み込みでは、バイトフィールドと文字フィールド(および1バイトのパディング)が読み込まれ、次の4バイトの読み込みでは整数フィールドが読み込まれます。期待どおりのパディングを追加するのは無駄です。合計サイズを小さくして同じ目標を達成することができます(予想したサイズを8バイト上回る8バイト)。

+0

ありがとうございます。あなたの答えは "ああ"の瞬間をもたらします。私の誤解は、すべての "チャック"が1つのフィールドでしか使用できないと思った。 –