Bagikan melalui


StructLayoutAttribute.Pack Bidang

Definisi

Mengontrol perataan bidang data dari kelas atau struktur dalam memori.

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

Nilai Bidang

Keterangan

Bidang Pack mengontrol perataan bidang jenis dalam memori. Ini mempengaruhi LayoutKind.Sequential properti . Nilai menunjukkan ukuran pengemasan default untuk platform saat ini. Nilai Pack harus 0, 1, 2, 4, 8, 16, 32, 64, atau 128. Nilai default adalah 0.

Bidang instans jenis diselaraskan dengan menggunakan aturan berikut:

  • Perataan jenis adalah ukuran elemen terbesarnya (misalnya, 1, 2, 4, atau 8 byte) atau ukuran pengemasan yang ditentukan, mana yang lebih kecil.
  • Setiap bidang harus selaras dengan bidang dengan ukurannya sendiri atau perataan jenis, mana yang lebih kecil. Karena perataan default jenis adalah ukuran elemen terbesarnya, yang lebih besar dari atau sama dengan semua panjang bidang lainnya, ini biasanya berarti bahwa bidang selaras dengan ukurannya. Misalnya, bahkan jika bidang terbesar dalam jenis adalah bilangan bulat 64-bit (8-byte) atau bidang Kemas diatur ke 8, Byte bidang selaras pada batas 1-byte, Int16 bidang yang selaras pada batas 2-byte, dan Int32 bidang yang selaras pada batas 4-byte.
  • Padding ditambahkan di antara bidang untuk memenuhi persyaratan penyelarasan.

Misalnya, pertimbangkan struktur berikut, yang terdiri dari dua Byte bidang dan satu Int32 bidang, saat digunakan dengan berbagai nilai untuk Pack bidang .

using System;

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

Penting

Agar berhasil mengkompilasi contoh C#, Anda harus menentukan sakelar /unsafe pengkompilasi.

Jika Anda menentukan ukuran pengemasan default, ukuran strukturnya adalah 8 byte. Dua byte menempati dua byte pertama memori, karena byte harus selaras pada batas satu byte. Karena perataan default jenis adalah 4 byte, yang merupakan ukuran bidang terbesarnya, i3, ada dua byte padding diikuti oleh bidang bilangan bulat.

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

Jika Pack diatur ke 2, ukuran struktur adalah 6 byte. Seperti sebelumnya, dua byte menempati dua byte pertama memori. Karena bidang sekarang selaras pada batas 2-byte, tidak ada padding antara byte kedua dan bilangan bulat.

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

Jika Pack diatur ke 4, ukuran struktur sama seperti dalam kasus default, di mana perataan jenis ditentukan oleh ukuran bidang terbesarnya, i3, yaitu 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

Jika Pack diatur ke 8, ukuran struktur masih sama seperti dalam kasus default, karena i3 bidang selaras pada batas 4-byte, yang lebih kecil dari batas 8-byte yang ditentukan oleh bidang Paket.

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

Untuk mengambil contoh lain, pertimbangkan struktur berikut, yang terdiri dari dua bidang byte, satu bidang bilangan bulat bertanda 32-bit, satu array byte elemen tunggal, dan nilai desimal. Dengan ukuran kemasan default, ukuran struktur adalah 28 byte dalam .NET Framework dan 32 byte di .NET 5+. Dua byte menempati dua byte pertama memori, diikuti oleh dua byte padding, diikuti oleh bilangan bulat. Selanjutnya adalah array satu byte, diikuti oleh tiga byte padding. Karena nilai desimal terdiri dari beberapa bidang, perataan didasarkan pada bidang terbesar daripada ukuran Decimal struktur secara keseluruhan. Dalam .NET 5 dan versi yang lebih baru, Decimal struktur terdiri dari dua Int32 bidang dan satu bidang 8-byte, sehingga Decimal bidang, d5, selaras pada batas 8-byte. Dalam .NET Framework, Decimal struktur terdiri dari empat Int32 bidang, sehingga Decimal bidang, d5, selaras pada batas 4-byte.

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

Jika Pack diatur ke 2, ukuran struktur adalah 24 byte. Dibandingkan dengan perataan default, dua byte pengisi antara dua byte dan bilangan bulat telah dihapus karena perataan jenis sekarang adalah 4, bukan 2. Dan tiga byte padding setelah a4 digantikan oleh satu byte padding, sejak d5 sekarang selaras pada batas 2-byte daripada batas 4-byte.

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

Jika Pack diatur ke 16, ukuran struktur sama seperti dalam kasus default, karena semua persyaratan penyelarasan dalam struktur ini kurang dari 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

Bidang Pack ini sering digunakan ketika struktur diekspor selama operasi penulisan disk dan jaringan. Bidang ini juga sering digunakan selama operasi pemanggilan platform dan interop.

Terkadang, bidang ini digunakan untuk mengurangi persyaratan memori dengan menghasilkan ukuran kemasan yang lebih ketat. Namun, penggunaan ini memerlukan pertimbangan yang cermat tentang batasan perangkat keras yang sebenarnya, dan mungkin benar-benar menurunkan performa.

Berlaku untuk