StructLayoutAttribute.Pack Pole
Definice
Důležité
Některé informace platí pro předběžně vydaný produkt, který se může zásadně změnit, než ho výrobce nebo autor vydá. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Řídí zarovnání datových polí třídy nebo struktury v paměti.
public: int Pack;
public int Pack;
val mutable Pack : int
Public Pack As Integer
Hodnota pole
Poznámky
Pole Pack řídí zarovnání polí typu v paměti. LayoutKind.SequentialOvlivňuje . Ve výchozím nastavení je hodnota 0, což označuje výchozí velikost balení pro aktuální platformu. Hodnota Pack musí být 0, 1, 2, 4, 8, 16, 32, 64 nebo 128:
Pole instance typu jsou zarovnaná pomocí následujících pravidel:
Zarovnání typu je velikost jeho největšího prvku (1, 2, 4, 8 atd., bajtů) nebo zadané velikosti balení podle toho, která velikost je menší.
Každé pole musí být zarovnané s poli vlastní velikosti (1, 2, 4, 8 atd., bajtů) nebo s zarovnáním typu podle toho, co je menší. Vzhledem k tomu, že výchozí zarovnání typu je velikost jeho největšího prvku, která je větší než nebo rovna všem ostatním délkám polí, obvykle to znamená, že pole jsou zarovnaná podle své velikosti. Například i když je největší pole v typu 64bitové (8babajtů) celé číslo nebo pole Pack je nastaveno na 8, Byte pole se zarovnají na 1bavových hranicích, Int16 pole se zarovnají na 2babajtů a Int32 pole se zarovnají na 4bavové hranice.
Odsazení je přidáno mezi pole, aby byly splněny požadavky na zarovnání.
Zvažte například následující strukturu, která se skládá ze dvou Byte polí a jednoho Int32 pole, pokud se používá s různými hodnotami pro Pack pole.
using System;
struct ExampleStruct
{
public byte b1;
public byte b2;
public int i3;
}
Důležité
Pokud chcete úspěšně zkompilovat příklady jazyka C#, musíte zadat přepínač kompilátoru /unsafe
.
Pokud zadáte výchozí velikost balení, bude velikost struktury 8 bajtů. Tyto dva bajty zabírají první dva bajty paměti, protože bajty se musí zarovnat na jednobajtů hranice. Vzhledem k tomu, že výchozí zarovnání typu je 4 bajty, což je velikost jeho největších polí, i3
existují dva bajty odsazení následované celočíselným polem.
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
Pokud Pack je nastavená hodnota 2, velikost struktury je 6 bajtů. Stejně jako předtím zabírají dva bajty první dva bajty paměti. Vzhledem k tomu, že pole se teď zarovnají na 2 bajtových hranicích, neexistuje mezi druhým bajtem a celočíselným číslem žádné odsazení.
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
Pokud Pack je nastavená hodnota 4, je velikost struktury stejná jako ve výchozím případě, kdy zarovnání typu bylo definováno velikostí jeho největšího pole , i3
což je 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
Pokud Pack je nastavena hodnota 8, velikost struktury je stále stejná jako ve výchozím případě, protože i3
pole je zarovnané na hranici 4 bajtů, která je menší než 8babajtů hranice určená polem Balíček.
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
Chcete-li použít jiný příklad, podívejte se na následující strukturu, která se skládá ze dvou bajtů, jednoho celočíselného pole se 32bitovým znakem, jednoho bajtového pole s jedním prvkem a desetinné hodnoty. Při výchozí velikosti balení je velikost struktury 28 bajtů. Dva bajty zabírají první dva bajty paměti, následované dvěma bajty odsazení a po nich celé číslo. Následuje jednobajtů pole následované třemi bajty odsazení. Decimal Nakonec se pole d5 zarovná na hranici 4 bajtů, protože desetinná hodnota se skládá ze čtyř Int32 polí, takže jeho zarovnání je založeno na velikosti největšího z jeho polí, nikoli na velikosti Decimal struktury jako celku.
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
Pokud Pack je nastavená hodnota 2, velikost struktury je 24 bajtů. Ve srovnání s výchozím zarovnáním byly odebrány dva bajty odsazení mezi dvěma bajty a celočíselným číslem, protože zarovnání typu je nyní 4 místo 2. A tři bajty odsazení byly a4
nahrazeny jedním bajtem odsazení, protože d5
nyní se zarovná na 2 bajtové hranici místo 4 bajtové hranice.
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
Pokud Pack je nastavená hodnota 8, velikost struktury je stejná jako ve výchozím případě, protože všechny požadavky na zarovnání v této struktuře jsou menší než 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
Toto Pack pole se často používá při exportu struktur během operací zápisu na disk a síť. Toto pole se také často používá při volání platformy a operacích vzájemné komunikace.
V některých případech se pole používá ke snížení požadavků na paměť tím, že vznikne užší velikost balení. Toto použití však vyžaduje pečlivé zvážení skutečných hardwarových omezení a může ve skutečnosti snížit výkon.
Platí pro
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro