StructLayoutAttribute.Pack フィールド
定義
重要
一部の情報は、リリース前に大きく変更される可能性があるプレリリースされた製品に関するものです。 Microsoft は、ここに記載されている情報について、明示または黙示を問わず、一切保証しません。
メモリ内のクラスまたは構造体のデータ フィールドのアライメントを制御します。
public: int Pack;
public int Pack;
val mutable Pack : int
Public Pack As Integer
フィールド値
注釈
フィールドは Pack 、メモリ内の型のフィールドの配置を制御します。 これは に影響します LayoutKind.Sequential。 既定では、値は 0 で、現在のプラットフォームの既定のパッキング サイズを示します。 の Pack 値は、0、1、2、4、8、16、32、64、または 128 である必要があります。
型インスタンスのフィールドは、次の規則を使用して配置されます。
型の配置は、最大要素 (1、2、4、8 など、バイト) または指定されたパッキング サイズのいずれか小さい方のサイズです。
各フィールドは、独自のサイズ (1、2、4、8、バイトなど) または型の配置のいずれか小さい方のフィールドと一致する必要があります。 型の既定の配置は、他のすべてのフィールド長以上の最大要素のサイズであるため、通常、フィールドはサイズに合わせて配置されます。 たとえば、型の最大フィールドが 64 ビット (8 バイト) の整数であるか、Pack フィールドが 8 に設定されている場合でも、 Byte フィールドは 1 バイト境界に揃え、 Int16 フィールドは 2 バイト境界に揃え、 Int32 フィールドは 4 バイト境界に揃えられます。
配置要件を満たすために、フィールド間にパディングが追加されます。
たとえば、2 つのフィールドと 1 つのByteInt32フィールドで構成される次の構造を、フィールドのさまざまな値と共にPack使用するとします。
using System;
struct ExampleStruct
{
public byte b1;
public byte b2;
public int i3;
}
重要
C# の例を正常にコンパイルするには、コンパイラ スイッチを指定する /unsafe
必要があります。
既定のパッキング サイズを指定した場合、構造体のサイズは 8 バイトです。 バイトは 1 バイト境界に揃える必要があるため、2 バイトは最初の 2 バイトのメモリを占有します。 型の既定の配置は 4 バイトであり、最大のフィールドのサイズであるため、 i3
埋め込みには 2 バイトの埋め込みが続き、整数フィールドが続きます。
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, Pack=0)]
struct ExampleStruct
{
public byte b1;
public byte b2;
public int i3;
}
public class Example
{
public unsafe static void Main()
{
ExampleStruct ex = new ExampleStruct();
byte* addr = (byte*) &ex;
Console.WriteLine("Size: {0}", sizeof(ExampleStruct));
Console.WriteLine("b1 Offset: {0}", &ex.b1 - addr);
Console.WriteLine("b2 Offset: {0}", &ex.b2 - addr);
Console.WriteLine("i3 Offset: {0}", (byte*) &ex.i3 - addr);
}
}
// The example displays the following output:
// Size: 8
// b1 Offset: 0
// b2 Offset: 1
// i3 Offset: 4
が 2 に設定されている場合 Pack 、構造体のサイズは 6 バイトです。 前と同様に、2 バイトは最初の 2 バイトのメモリを占有します。 フィールドは 2 バイトの境界に揃えられるようになったため、2 番目のバイトと整数の間にパディングはありません。
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, Pack=2)]
struct ExampleStruct
{
public byte b1;
public byte b2;
public int i3;
}
public class Example
{
public unsafe static void Main()
{
ExampleStruct ex = new ExampleStruct();
byte* addr = (byte*) &ex;
Console.WriteLine("Size: {0}", sizeof(ExampleStruct));
Console.WriteLine("b1 Offset: {0}", &ex.b1 - addr);
Console.WriteLine("b2 Offset: {0}", &ex.b2 - addr);
Console.WriteLine("i3 Offset: {0}", (byte*) &ex.i3 - addr);
}
}
// The example displays the following output:
// Size: 6
// b1 Offset: 0
// b2 Offset: 1
// i3 Offset: 2
が 4 に設定されている場合 Pack 、構造体のサイズは既定の場合と同じになります。この場合、型の配置は最大フィールド i3
のサイズ (4) で定義されています。
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, Pack=4)]
struct ExampleStruct
{
public byte b1;
public byte b2;
public int i3;
}
public class Example
{
public unsafe static void Main()
{
ExampleStruct ex = new ExampleStruct();
byte* addr = (byte*) &ex;
Console.WriteLine("Size: {0}", sizeof(ExampleStruct));
Console.WriteLine("b1 Offset: {0}", &ex.b1 - addr);
Console.WriteLine("b2 Offset: {0}", &ex.b2 - addr);
Console.WriteLine("i3 Offset: {0}", (byte*) &ex.i3 - addr);
}
}
// The example displays the following output:
// Size: 8
// b1 Offset: 0
// b2 Offset: 1
// i3 Offset: 4
が 8 に設定されている場合 Pack 、構造体のサイズは既定の場合と同じです。これは、フィールドが 4 バイト境界に揃っているため i3
です。これは、Pack フィールドで指定された 8 バイト境界よりも小さくなります。
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, Pack=8)]
struct ExampleStruct
{
public byte b1;
public byte b2;
public int i3;
}
public class Example
{
public unsafe static void Main()
{
ExampleStruct ex = new ExampleStruct();
byte* addr = (byte*) &ex;
Console.WriteLine("Size: {0}", sizeof(ExampleStruct));
Console.WriteLine("b1 Offset: {0}", &ex.b1 - addr);
Console.WriteLine("b2 Offset: {0}", &ex.b2 - addr);
Console.WriteLine("i3 Offset: {0}", (byte*) &ex.i3 - addr);
}
}
// The example displays the following output:
// Size: 8
// b1 Offset: 0
// b2 Offset: 1
// i3 Offset: 4
別の例を見ると、2 つのバイト フィールド、1 つの 32 ビット符号付き整数フィールド、1 つの単一要素バイト配列、および 10 進値で構成される次の構造について考えてみましょう。 既定のパッキング サイズでは、構造体のサイズは 28 バイトです。 2 バイトは最初の 2 バイトのメモリを占有し、その後に 2 バイトのパディングが続き、その後に整数が続きます。 次に、1 バイトの配列の後に 3 バイトのパディングが続きます。 最後に、 Decimal 10 進値が 4 つのフィールドで構成されるため、フィールド d5 は 4 Int32 バイト境界に配置されるため、その配置は構造体全体のサイズではなく、最大のフィールドの Decimal サイズに基づきます。
using System;
using System.Runtime.InteropServices;
unsafe struct ExampleStruct2
{
public byte b1;
public byte b2;
public int i3;
public fixed byte a4[1];
public decimal d5;
}
public class Example
{
public unsafe static void Main()
{
ExampleStruct2 ex = new ExampleStruct2();
byte* addr = (byte*) &ex;
Console.WriteLine("Size: {0}", sizeof(ExampleStruct2));
Console.WriteLine("b1 Offset: {0}", &ex.b1 - addr);
Console.WriteLine("b2 Offset: {0}", &ex.b2 - addr);
Console.WriteLine("i3 Offset: {0}", (byte*) &ex.i3 - addr);
Console.WriteLine("a4 Offset: {0}", ex.a4 - addr);
Console.WriteLine("d5 Offset: {0}", (byte*) &ex.d5 - addr);
}
}
// The example displays the following output:
// Size: 28
// b1 Offset: 0
// b2 Offset: 1
// i3 Offset: 4
// a4 Offset: 8
// d5 Offset: 12
が 2 に設定されている場合 Pack 、構造体のサイズは 24 バイトです。 既定のアラインメントと比較して、2 バイトと整数の間の 2 バイトのパディングは削除されました。これは、型のアラインメントが 2 ではなく 4 であるためです。 以降の 3 バイトのパディング a4
は、4 バイトの境界ではなく 2 バイトの境界に配置されるため d5
、1 バイトのパディングに置き換えられました。
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, Pack = 2)]
unsafe struct ExampleStruct2
{
public byte b1;
public byte b2;
public int i3;
public fixed byte a4[1];
public decimal d5;
}
public class Example
{
public unsafe static void Main()
{
ExampleStruct2 ex = new ExampleStruct2();
byte* addr = (byte*) &ex;
Console.WriteLine("Size: {0}", sizeof(ExampleStruct2));
Console.WriteLine("b1 Offset: {0}", &ex.b1 - addr);
Console.WriteLine("b2 Offset: {0}", &ex.b2 - addr);
Console.WriteLine("i3 Offset: {0}", (byte*) &ex.i3 - addr);
Console.WriteLine("a4 Offset: {0}", ex.a4 - addr);
Console.WriteLine("d5 Offset: {0}", (byte*) &ex.d5 - addr);
}
}
// The example displays the following output:
// Size: 24
// b1 Offset: 0
// b2 Offset: 1
// i3 Offset: 2
// a4 Offset: 6
// d5 Offset: 8
が 8 に設定されている場合 Pack 、構造体のサイズは既定の場合と同じです。これは、この構造体のすべての配置要件が 8 未満であるためです。
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, Pack = 8)]
unsafe struct ExampleStruct2
{
public byte b1;
public byte b2;
public int i3;
public fixed byte a4[1];
public decimal d5;
}
public class Example
{
public unsafe static void Main()
{
ExampleStruct2 ex = new ExampleStruct2();
byte* addr = (byte*) &ex;
Console.WriteLine("Size: {0}", sizeof(ExampleStruct2));
Console.WriteLine("b1 Offset: {0}", &ex.b1 - addr);
Console.WriteLine("b2 Offset: {0}", &ex.b2 - addr);
Console.WriteLine("i3 Offset: {0}", (byte*) &ex.i3 - addr);
Console.WriteLine("a4 Offset: {0}", ex.a4 - addr);
Console.WriteLine("d5 Offset: {0}", (byte*) &ex.d5 - addr);
}
}
// The example displays the following output:
// Size: 28
// b1 Offset: 0
// b2 Offset: 1
// i3 Offset: 4
// a4 Offset: 8
// d5 Offset: 12
この Pack フィールドは、ディスクおよびネットワーク書き込み操作中に構造体がエクスポートされるときによく使用されます。 このフィールドは、プラットフォーム呼び出しおよび相互運用操作中にも頻繁に使用されます。
場合によっては、 フィールドを使用して、より厳密なパッキング サイズを生成することでメモリ要件を減らします。 ただし、この使用には実際のハードウェア制約を慎重に考慮する必要があり、実際にはパフォーマンスが低下する可能性があります。
適用対象
.NET
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示