StructLayoutAttribute.Pack Alan

Tanım

Bellekteki bir sınıfın veya yapının veri alanlarının hizalamasını denetler.

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

Alan Değeri

Açıklamalar

Alan, Pack bellekteki tür alanlarının hizalamasını denetler. Özelliği etkiler LayoutKind.Sequential . değeri geçerli platform için varsayılan paketleme boyutunu gösterir. değeri Pack 0, 1, 2, 4, 8, 16, 32, 64 veya 128 olmalıdır. Varsayılan değer 0’dır.

Tür örneğinin alanları aşağıdaki kurallar kullanılarak hizalanır:

  • Bir türün hizalaması, en büyük öğesinin boyutu (örneğin, 1, 2, 4 veya 8 bayt) veya belirtilen paketleme boyutudur (hangisi daha küçükse).
  • Her alan, kendi boyutundaki alanlarla veya türün hizalamasıyla (hangisi daha küçükse) hizalanmalıdır. Türün varsayılan hizalaması, diğer tüm alan uzunluklarından büyük veya buna eşit olan en büyük öğesinin boyutu olduğundan, bu genellikle alanların boyutlarına göre hizalandığı anlamına gelir. Örneğin, bir türdeki en büyük alan 64 bit (8 bayt) bir tamsayı veya Paket alanı 8 olarak ayarlanmış olsa bile, Byte alanlar 1 baytlık sınırlara hizalanır, Int16 alanlar 2 baytlık sınırlara hizalanır ve Int32 alanlar 4 baytlık sınırlara hizalanır.
  • Hizalama gereksinimlerini karşılamak için alanlar arasına doldurma eklenir.

Örneğin, alan için çeşitli değerlerle kullanıldığında iki Byte alan ve bir Int32 alandan oluşan aşağıdaki yapıyı Pack göz önünde bulundurun.

using System;

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

Önemli

C# örneklerini başarıyla derlemek için derleyici anahtarını belirtmeniz /unsafe gerekir.

Varsayılan paketleme boyutunu belirtirseniz, yapının boyutu 8 bayttır. Baytların tek baytlık sınırlara hizalanmış olması gerektiğinden, iki bayt belleğin ilk iki baytını kaplar. Türün varsayılan hizalaması en büyük alanlarının boyutu olan 4 bayt olduğundan, i3iki bayt doldurma ve ardından tamsayı alanı vardır.

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

2 olarak ayarlanırsa Pack , yapının boyutu 6 bayttır. Daha önce olduğu gibi, iki bayt belleğin ilk iki baytını kaplar. Alanlar artık 2 baytlık sınırlara hizalanmış olduğundan, ikinci bayt ile tamsayı arasında doldurma yoktur.

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

4 olarak ayarlanırsa Pack , yapının boyutu varsayılan durumdakiyle aynıdır; burada türün hizalaması en büyük alanı i3olan 4'ün boyutuyla tanımlanmıştır.

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

8 olarak ayarlanırsa Pack , alan Pack alanı tarafından belirtilen 8 baytlık sınırdan daha küçük olan 4 baytlık bir sınıra hizalandığından, yapının boyutu varsayılan durumdakiyle i3 aynıdır.

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

Başka bir örnek almak için, iki bayt alanı, bir 32 bit imzalı tamsayı alanı, bir tek öğeli bayt dizisi ve ondalık değerden oluşan aşağıdaki yapıyı göz önünde bulundurun. Varsayılan paketleme boyutuyla, yapının boyutu .NET Framework'te 28 bayt ve .NET 5+ içinde 32 bayttır. İki bayt, belleğin ilk iki baytını ve ardından iki doldurma baytını ve ardından tamsayıyı kaplar. Sonraki tek baytlık dizi, ardından üç bayt doldurma. Ondalık değer birkaç alandan oluştuğundan, hizalama bir bütün olarak yapının boyutu yerine alanlarının Decimal en büyüğe dayanır. .NET 5 ve sonraki sürümlerinde, Decimal yapı iki Int32 alandan ve bir 8 baytlık alandan Decimal oluşur, bu nedenle d5 alanı 8 baytlık bir sınıra hizalanır. .NET Framework'te Decimal yapı dört Int32 alandan oluşur, bu nedenle Decimal d5 alanı 4 baytlık bir sınıra hizalanır.

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

2 olarak ayarlanırsa Pack , yapının boyutu 24 bayttır. Varsayılan hizalamaya kıyasla, türün hizalaması artık 2 yerine 4 olduğundan, iki bayt ile tamsayı arasındaki iki doldurma baytları kaldırılmıştır. Sonrasındaki üç doldurma a4 baytı bir bayt doldurma ile değiştirilmiştir, çünkü d5 artık 4 baytlık bir sınır yerine 2 baytlık bir sınıra hizalanır.

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

16 olarak ayarlanırsa Pack , bu yapıdaki tüm hizalama gereksinimleri 16'dan küçük olduğundan, yapının boyutu varsayılan durumdakiyle aynıdır.

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

Alan Pack , disk ve ağ yazma işlemleri sırasında yapılar dışarı aktarıldığında sıklıkla kullanılır. Bu alan ayrıca platform çağırma ve birlikte çalışma işlemleri sırasında da sık kullanılır.

Bazen alan, daha dar bir paketleme boyutu üreterek bellek gereksinimlerini azaltmak için kullanılır. Ancak, bu kullanım gerçek donanım kısıtlamalarının dikkatli bir şekilde değerlendirilmesini gerektirir ve performansı düşürebilir.

Şunlara uygulanır