StructLayoutAttribute.Pack Pole

Definice

Řídí zarovnání datových polí třídy nebo struktury v paměti.

public: int Pack;
public int Pack;
val mutable Pack : int
Public Pack As Integer 

Hodnota pole

Poznámky

Pole Pack řídí zarovnání polí typu v paměti. LayoutKind.SequentialOvlivňuje . Ve výchozím nastavení je hodnota 0, což označuje výchozí velikost balení pro aktuální platformu. Hodnota Pack musí být 0, 1, 2, 4, 8, 16, 32, 64 nebo 128:

Pole instance typu jsou zarovnaná pomocí následujících pravidel:

  • Zarovnání typu je velikost jeho největšího prvku (1, 2, 4, 8 atd., bajtů) nebo zadané velikosti balení podle toho, která velikost je menší.

  • Každé pole musí být zarovnané s poli vlastní velikosti (1, 2, 4, 8 atd., bajtů) nebo s zarovnáním typu podle toho, co je menší. Vzhledem k tomu, že výchozí zarovnání typu je velikost jeho největšího prvku, která je větší než nebo rovna všem ostatním délkám polí, obvykle to znamená, že pole jsou zarovnaná podle své velikosti. Například i když je největší pole v typu 64bitové (8babajtů) celé číslo nebo pole Pack je nastaveno na 8, Byte pole se zarovnají na 1bavových hranicích, Int16 pole se zarovnají na 2babajtů a Int32 pole se zarovnají na 4bavové hranice.

  • Odsazení je přidáno mezi pole, aby byly splněny požadavky na zarovnání.

Zvažte například následující strukturu, která se skládá ze dvou Byte polí a jednoho Int32 pole, pokud se používá s různými hodnotami pro Pack pole.

using System;

struct ExampleStruct
{
   public byte b1;
   public byte b2;
   public int i3;
}

Důležité

Pokud chcete úspěšně zkompilovat příklady jazyka C#, musíte zadat přepínač kompilátoru /unsafe .

Pokud zadáte výchozí velikost balení, bude velikost struktury 8 bajtů. Tyto dva bajty zabírají první dva bajty paměti, protože bajty se musí zarovnat na jednobajtů hranice. Vzhledem k tomu, že výchozí zarovnání typu je 4 bajty, což je velikost jeho největších polí, i3existují dva bajty odsazení následované celočíselným polem.

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

Pokud Pack je nastavená hodnota 2, velikost struktury je 6 bajtů. Stejně jako předtím zabírají dva bajty první dva bajty paměti. Vzhledem k tomu, že pole se teď zarovnají na 2 bajtových hranicích, neexistuje mezi druhým bajtem a celočíselným číslem žádné odsazení.

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

Pokud Pack je nastavená hodnota 4, je velikost struktury stejná jako ve výchozím případě, kdy zarovnání typu bylo definováno velikostí jeho největšího pole , i3což je 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

Pokud Pack je nastavena hodnota 8, velikost struktury je stále stejná jako ve výchozím případě, protože i3 pole je zarovnané na hranici 4 bajtů, která je menší než 8babajtů hranice určená polem Balíček.

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

Chcete-li použít jiný příklad, podívejte se na následující strukturu, která se skládá ze dvou bajtů, jednoho celočíselného pole se 32bitovým znakem, jednoho bajtového pole s jedním prvkem a desetinné hodnoty. Při výchozí velikosti balení je velikost struktury 28 bajtů. Dva bajty zabírají první dva bajty paměti, následované dvěma bajty odsazení a po nich celé číslo. Následuje jednobajtů pole následované třemi bajty odsazení. Decimal Nakonec se pole d5 zarovná na hranici 4 bajtů, protože desetinná hodnota se skládá ze čtyř Int32 polí, takže jeho zarovnání je založeno na velikosti největšího z jeho polí, nikoli na velikosti Decimal struktury jako celku.

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

Pokud Pack je nastavená hodnota 2, velikost struktury je 24 bajtů. Ve srovnání s výchozím zarovnáním byly odebrány dva bajty odsazení mezi dvěma bajty a celočíselným číslem, protože zarovnání typu je nyní 4 místo 2. A tři bajty odsazení byly a4 nahrazeny jedním bajtem odsazení, protože d5 nyní se zarovná na 2 bajtové hranici místo 4 bajtové hranice.

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

Pokud Pack je nastavená hodnota 8, velikost struktury je stejná jako ve výchozím případě, protože všechny požadavky na zarovnání v této struktuře jsou menší než 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

Toto Pack pole se často používá při exportu struktur během operací zápisu na disk a síť. Toto pole se také často používá při volání platformy a operacích vzájemné komunikace.

V některých případech se pole používá ke snížení požadavků na paměť tím, že vznikne užší velikost balení. Toto použití však vyžaduje pečlivé zvážení skutečných hardwarových omezení a může ve skutečnosti snížit výkon.

Platí pro