StructLayoutAttribute.Pack StructLayoutAttribute.Pack StructLayoutAttribute.Pack StructLayoutAttribute.Pack Field

定义

控制类或结构的数据字段在内存中的对齐方式。Controls the alignment of data fields of a class or structure in memory.

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

字段值

注解

Pack字段控制在内存中的类型的字段的对齐方式。The Pack field controls the alignment of a type's fields in memory. 它会同时影响LayoutKind.SequentialLayoutKind.ExplicitIt affects both LayoutKind.Sequential and LayoutKind.Explicit. 默认情况下,值为 0,表示默认包装大小对于当前平台。By default, the value is 0, indicating the default packing size for the current platform. Pack必须是 0、 1、 2、 4、 8、 16、 32、 64 或 128:The value of Pack must be 0, 1, 2, 4, 8, 16, 32, 64, or 128:

使用以下规则按对齐类型实例的字段:The fields of a type instance are aligned by using the following rules:

  • 类型的对齐方式是其最大元素的大小 (1、 2、 4、 8,等等,字节数) 或指定的封装大小,以二者中较小者为准。The alignment of the type is the size of its largest element (1, 2, 4, 8, etc., bytes) or the specified packing size, whichever is smaller.

  • 每个字段必须与字段其自身的大小保持一致 (1、 2、 4、 8,等等,字节数) 的对齐方式的类型,或两者中较小。Each field must align with fields of its own size (1, 2, 4, 8, etc., bytes) or the alignment of the type, whichever is smaller. 类型的默认对齐方式是为大于或等于所有其他字段长度,其最大元素的大小,因为这通常意味着字段对齐按其大小。Because the default alignment of the type is the size of its largest element, which is greater than or equal to all other field lengths, this usually means that fields are aligned by their size. 例如,即使在类型中的最大字段是 64 位 (8 字节) 整数或包字段设置为 8,Byte字段在 1 字节边界上对齐Int16在 2 字节边界上对齐字段和Int32字段在 4 字节边界上对齐。For example, even if the largest field in a type is a 64-bit (8-byte) integer or the Pack field is set to 8, Byte fields align on 1-byte boundaries, Int16 fields align on 2-byte boundaries, and Int32 fields align on 4-byte boundaries.

  • 若要满足的对齐要求的字段之间添加填充。Padding is added between fields to satisfy the alignment requirements.

例如,假设具有以下结构,包含两个Byte字段和一个Int32字段中,它使用的各个值时Pack字段。For example, consider the following structure, which consists of two Byte fields and one Int32 field, when it is used with various values for the Pack field.

using System;

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

重要

若要成功编译的 C# 示例,必须指定/unsafe编译器开关。To successfully compile the C# examples, you must specify the /unsafe compiler switch.

如果指定默认包装大小,该结构的大小是 8 个字节。If you specify the default packing size, the size of the structure is 8 bytes. 两个字节占用的内存前, 两个字节,因为字节必须在单字节边界上对齐。The two bytes occupy the first two bytes of memory, because bytes must align on one-byte boundaries. 类型的默认对齐方式为 4 个字节,这是其最大字段的大小,因为i3,有两个字节的整数字段后跟的填充。Because the default alignment of the type is 4 bytes, which is the size of its largest fields, i3, there are two bytes of padding followed by the integer field.

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

如果Pack设置为 2,结构的大小为 6 个字节。If Pack is set to 2, the size of the structure is 6 bytes. 为之前,两个字节都占用内存的前两个字节。As before, the two bytes occupy the first two bytes of memory. 因为字段现在在 2 字节边界上对齐,则无需进行填充第二个字节和整数之间。Because fields now align on 2-byte boundaries, there is no padding between the second byte and the integer.

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

如果Pack设置为 4,结构的大小是默认情况下,该类型的对齐方式定义的位置由其最大字段大小,相同i3,为 4。If Pack is set to 4, the size of the structure is the same as in the default case, where the type's alignment was defined by the size of its largest field, i3, which is 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

如果Pack设置为 8,结构的大小是仍与默认值相同情况下,因为i3字段将 4 字节边界,即小于由包字段指定的 8 字节边界上对齐。If Pack is set to 8, the size of the structure is the still same as in the default case, because the i3 field aligns on a 4-byte boundary, which is smaller than the 8-byte boundary specified by the Pack field.

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

若要另一个示例,请考虑以下结构,它包含两个字节的字段、 一个 32 位有符号的整数字段、 一个单元素字节数组和一个十进制值。To take another example, consider the following structure, which consists of two byte fields, one 32-bit signed integer field, one single-element byte array, and a decimal value. 使用默认包装大小,结构的大小为 28 个字节。With the default packing size, the size of the structure is 28 bytes. 两个字节占用的内存后, 跟两个字节的填充,整数后跟前两个字节。The two bytes occupy the first two bytes of memory, followed by two bytes of padding, followed by the integer. 接下来是填充的单字节数组后, 跟三个字节。Next is the one-byte array, followed by three bytes of padding. 最后,Decimal因为十进制值包含以下四个字段,d5,对齐 4 字节边界上Int32字段,因此其对齐将基于最大大小的其字段,而不是大小Decimal作为一个整体结构。Finally, the Decimal field, d5, aligns on a 4-byte boundary because a decimal value consists of four Int32 fields, so its alignment is based on the size of the largest of its fields rather than on the size of the Decimal structure as a whole.

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

如果Pack设置为 2,结构的大小为 24 个字节。If Pack is set to 2, the size of the structure is 24 bytes. 与默认对齐方式,相比两个字节的两个字节和整数之间的填充已被删除,因为该类型的对齐方式现在是 4,而不是 2。In comparison with the default alignment, the two bytes of padding between the two bytes and the integer have been removed because the type's alignment is now 4 rather than 2. 和后填充三个字节a4已替换为一个字节的填充,因为d5现在 2 字节边界而不是 4 字节边界上对齐。And the three bytes of padding after a4 have been replaced by one byte of padding, since d5 now aligns on a 2-byte boundary rather than a 4-byte boundary.

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

如果Pack设置结构的大小为 8,是相同默认情况下,因为在此结构中的所有对齐要求小于 8。If Pack is set to 8, the size of the structure is the same as in the default case, because all the alignment requirements in this structure are less than 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

Pack结构导出期间磁盘和网络写入操作时,经常使用字段。The Pack field is frequently used when structures are exported during disk and network write operations. 字段通常也会使用在平台调用和互操作的操作。The field is also frequently used during platform invoke and interop operations.

有时,字段用于通过生成更紧密的封装大小来减少内存需求。Occasionally, the field is used to reduce memory requirements by producing a tighter packing size. 但是,这种用法需要仔细考虑的实际硬件约束,并且可能会降低性能。However, this usage requires careful consideration of actual hardware constraints, and may actually degrade performance.

适用于