StructLayoutAttribute.Pack Alan
Tanım
Önemli
Bazı bilgiler ürünün ön sürümüyle ilgilidir ve sürüm öncesinde önemli değişiklikler yapılmış olabilir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.
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 bir türün 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'tir.
Bir 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 alandan 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;
}
Important
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 bayt sınırlarına 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, türün hizalamasının 4 olan en büyük alanının i3boyutuyla tanımlandığı varsayılan durumla aynıdı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+ cinsinden 32 bayttır. İki bayt, belleğin ilk iki baytını, ardından iki bayt doldurmayı ve ardından tamsayıyı kaplar. Sonraki tek baytlık dizi ve 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ümlerde Decimal yapısı iki Int32 alanından ve bir 8 baytlık alandan oluşur; bu nedenle Decimal alanı d5, 8 baytlık bir sınıra hizalanır. .NET Framework'te Decimal yapısı dört Int32 alanından oluşur; bu nedenle Decimal alanı olan d5, 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 üç bayt doldurma a4 , artık 4 baytlık bir sınır yerine 2 baytlık bir sınıra hizalanmış olduğundan d5 , bir bayt doldurma ile değiştirilmiştir.
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
Bu Pack alan, yapılar disk ve ağ yazma işlemleri sırasında dışarı aktarıldığında sıklıkla kullanılır. Bu alan, platform çağırma ve birlikte çalışma işlemleri sırasında da sık sık kullanılır.
Bazen, alan daha sıkı bir ambalaj 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 dikkate alınmasını gerektirir ve performansı düşürebilir.