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. Secara default, nilainya adalah 0, menunjukkan ukuran pengemasan default untuk platform saat ini. Nilai Pack harus 0, 1, 2, 4, 8, 16, 32, 64, atau 128:

Bidang instans jenis diselaraskan dengan menggunakan aturan berikut:

  • Perataan jenis adalah ukuran elemen terbesarnya (1, 2, 4, 8, dll., byte) atau ukuran pengemasan yang ditentukan, mana yang lebih kecil.

  • Setiap bidang harus selaras dengan bidang dengan ukurannya sendiri (1, 2, 4, 8, dll., byte) atau perataan jenis, mana pun 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, ketika 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 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

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 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

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 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

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 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

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 pengemasan default, ukuran strukturnya adalah 28 byte. 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. Akhirnya, Decimal bidang, d5, selaras pada batas 4-byte karena nilai desimal terdiri dari empat Int32 bidang, sehingga perataannya didasarkan pada ukuran yang terbesar dari bidangnya daripada pada ukuran Decimal struktur secara keseluruhan.

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

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 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

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

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