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.Sequential Ovlivňuje vlastnost. Hodnota 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. Výchozí hodnota je 0.

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

  • Zarovnání typu je velikost jeho největšího prvku (například 1, 2, 4 nebo 8 bajtů) nebo zadané velikosti balení, podle toho, co je menší.
  • Každé pole musí být v souladu s poli vlastní velikosti nebo 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ší nebo roven všem ostatním délkám pole, obvykle to znamená, že pole jsou zarovnaná podle jejich velikosti. I když je například největší pole typu 64bitové celé číslo (8 bajtů) nebo je pole Pack nastaveno na 8, Byte pole se zarovnají na 1 bajtové hranice, Int16 pole se zarovnají na 2 bajtových hranicích a Int32 pole se zarovnají na 4 bajtových hranicích.
  • Odsazení se přidá mezi pole, aby vyhovovalo požadavkům na zarovnání.

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

using System;

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

Important

Chcete-li úspěšně zkompilovat příklady jazyka C#, je nutné zadat přepínač kompilátoru /unsafe .

Pokud zadáte výchozí velikost balení, velikost struktury je 8 bajtů. Dva bajty zabírají první dva bajty paměti, protože bajty se musí zarovnat na hranice 1 bajtů. 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é pole.

using System;
using System.Runtime.InteropServices;

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

public class Example1
{
    public unsafe static void Main()
    {
        ExampleStruct1 ex = new();
        byte* addr = (byte*)&ex;
        Console.WriteLine("Size:      {0}", sizeof(ExampleStruct1));
        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 na 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 dvou bajtových hranicích, mezi druhým bajtem a celým číslem neexistuje žádné odsazení.

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 2)]
struct ExampleStruct2
{
    public byte b1;
    public byte b2;
    public int i3;
}

public class Example2
{
    public unsafe static void Main()
    {
        ExampleStruct2 ex = new();
        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);
    }
}
// The example displays the following output:
//       Size:      6
//       b1 Offset: 0
//       b2 Offset: 1
//       i3 Offset: 2

Pokud Pack je nastavena na 4, velikost struktury je stejná jako ve výchozím případě, kde 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 ExampleStruct3
{
    public byte b1;
    public byte b2;
    public int i3;
}

public class Example3
{
    public unsafe static void Main()
    {
        ExampleStruct3 ex = new();
        byte* addr = (byte*)&ex;
        Console.WriteLine("Size:      {0}", sizeof(ExampleStruct3));
        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 8, velikost struktury je stále stejná jako ve výchozím případě, protože i3 pole se zarovná na hranici 4 bajtů, která je menší než 8 bajtová hranice určená polem Pack.

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 8)]
struct ExampleStruct4
{
    public byte b1;
    public byte b2;
    public int i3;
}

public class Example4
{
    public unsafe static void Main()
    {
        ExampleStruct4 ex = new();
        byte* addr = (byte*)&ex;
        Console.WriteLine("Size:      {0}", sizeof(ExampleStruct4));
        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 chcete vzít další příklad, zvažte následující strukturu, která se skládá ze dvou bajtových polí, jednoho 32bitového bitového celého pole se dvěma bajtů, jednočlenného bajtového pole a desetinné hodnoty. S výchozí velikost balení je velikost struktury 28 bajtů v .NET Framework a 32 bajtů v .NET 5 +. Dva bajty zabírají první dva bajty paměti, následované dvěma bajty odsazení, následovanými celými čísly. Dále je jednobajtů pole následované třemi bajty odsazení. Vzhledem k tomu, že desetinná hodnota se skládá z několika polí, zarovnání vychází z největších polí, nikoli na velikosti Decimal struktury jako celku. V .NET 5 a novějších verzích se struktura Decimal skládá ze dvou polí Int32 a jednoho pole s 8 bajty, takže pole Decimal d5 se zarovná na 8 bajtové hranici. V .NET Frameworku se struktura Decimal skládá ze čtyř polí Int32, takže Decimal pole d5 se zarovná na hranici 4 bajtů.

using System;

unsafe struct ExampleStruct5
{

    public byte b1;
    public byte b2;
    public int i3;
    public fixed byte a4[1];
    public decimal d5;
}

public class Example5
{
    public unsafe static void Main()
    {
        ExampleStruct5 ex = new();
        byte* addr = (byte*)&ex;
        Console.WriteLine("Size:      {0}", sizeof(ExampleStruct5));
        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:
//
// .NET 5+:
//       Size:      32
//       b1 Offset: 0
//       b2 Offset: 1
//       i3 Offset: 4
//       a4 Offset: 8
//       d5 Offset: 16
//
// .NET Framework:
//       Size:      28
//       b1 Offset: 0
//       b2 Offset: 1
//       i3 Offset: 4
//       a4 Offset: 8
//       d5 Offset: 12

Pokud Pack je nastavena na 2, velikost struktury je 24 bajtů. Ve srovnání s výchozím zarovnáním byly dva bajty odsazení mezi dvěma bajty a celé číslo odebrány, 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 bajtovou hranici, nikoli na 4 bajtovou hranici.

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 2)]
unsafe struct ExampleStruct6
{

    public byte b1;
    public byte b2;
    public int i3;
    public fixed byte a4[1];
    public decimal d5;
}

public class Example6
{
    public unsafe static void Main()
    {
        ExampleStruct6 ex = new();
        byte* addr = (byte*)&ex;
        Console.WriteLine("Size:      {0}", sizeof(ExampleStruct6));
        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 16, 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ž 16.

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 16)]
unsafe struct ExampleStruct7
{

    public byte b1;
    public byte b2;
    public int i3;
    public fixed byte a4[1];
    public decimal d5;
}

public class Example7
{
    public unsafe static void Main()
    {
        ExampleStruct7 ex = new();
        byte* addr = (byte*)&ex;
        Console.WriteLine("Size:      {0}", sizeof(ExampleStruct7));
        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:
//
// .NET 5+:
//       Size:      32
//       b1 Offset: 0
//       b2 Offset: 1
//       i3 Offset: 4
//       a4 Offset: 8
//       d5 Offset: 16
//
// .NET Framework:
//       Size:      28
//       b1 Offset: 0
//       b2 Offset: 1
//       i3 Offset: 4
//       a4 Offset: 8
//       d5 Offset: 12

Pole Pack 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 operacích volání platformy a vzájemné spolupráce.

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

Platí pro