zarovnání (C++)
Konkrétní společnosti Microsoft
Použití __declspec(align(#)) přesně řídit zarovnání dat definované uživatelem (například statické přidělení nebo automatické datové funkce).
Další informace o zarovnání, viz Windows zarovnání dat na IPF x 86 a x 64.
__declspec( align( # ) ) declarator
Poznámky
Psaní aplikací, které používají nejnovější pokyny procesoru zavádí některé nové omezení a problémy.Mnoho nových pokynů zejména požadovat data vyrovnají hranice 16 bajtů.Navíc často používané datové velikosti řádku mezipaměti specifické procesoru sladěním zlepšení výkonu mezipaměti.Například pokud definujete strukturu, jejichž velikost je menší než 32 bajtů, můžete zarovnat k zajištění efektivní ukládány objekty typu Struktura 32 bajtů.
# Hodnota zarovnání.Platné položky jsou dvě z 1 8192 (bajty), jako je například 2, 4, 8, 16, 32 nebo 64 pravomoci celé číslo.declaratorjsou data, která deklarujete jako zarovnány.
Viz __alignof informace, jak vrátit hodnotu typu size_t je zarovnání požadavek typu.a __unaligned informace, jak deklarovat nezarovnané ukazatele při cílení 64bitové procesory.
Můžete použít __declspec(align(#)) při definování struct, union, nebo class, nebo když deklarujete proměnnou.
Bez __declspec(align(#)), Visual C++ Zarovná data na přirozené hranice v závislosti na velikosti dat, například 4bajtové celá na 4 bajtů a 8 2bajtový na 8 bajtů.Data třídy nebo struktury je zarovnána v rámci třídy nebo struktury minimálně na jeho přirozené zarovnání a aktuální nastavení balného (z # pragma pack nebo /Zp volba kompilátoru).
Nelze zadat parametry funkce zarovnání.
Příklad:
__declspec(align(32)) struct Str1{
int a, b, c, d, e;
};
Tento typ nyní obsahuje atribut zarovnání 32 bajtů, což znamená, že všechny instance musí začínat na hranici 32 bajtů.Struktura další typy deklarované pomocí tohoto typu jako člen zachovat tento typ atributu zarovnání, je libovolné struktury s Str1 jako prvek atributu zarovnání alespoň 32.
Shrnout:
Pokud nejsou přepsány s __declspec(align(#)), zarovnání skalární strukturu členu je minimální velikosti a aktuální balení.
Pokud nejsou přepsány s __declspec(align(#)), zarovnání struktury je maximální individuální zarovnání jeho členy.
Struktura členské umístěn v posunu od začátku její nadřazené konstrukce, který je nejmenší více jeho zarovnání větší nebo rovna posun konec předchozí člen.
Velikost struktury je nejmenší více jeho zarovnání větší větší než nebo rovno posun na konci posledního člena.
Všimněte si, že sizeof(struct Str1) je rovna 32, takové, že pokud je vytvořena pole objektů Str1 a Základní matice je 32 bajtů, zarovnání, pak každý člen pole bude také zarovnány 32 bajtů.Chcete-li vytvořit pole, jehož základ správně zarovnány, použijte _aligned_malloc, nebo napsat vlastní přidělování.Všimněte si, že normální allocators, jako například malloc, C++ nový operátor, a Win32 allocators vrátit paměť, která pravděpodobně není zarovnán dostatečně pro **__**declspec(align(#)) struktury nebo pole struktur.
sizeof Žádnou strukturu hodnotu Posun poslední člen plus velikost daného člena, zaokrouhlený na nejbližší násobek největší hodnotu člena zarovnání nebo zarovnání hodnotu celé struktury, je tato hodnota vyšší.
__declspec(align(#))pouze zvýšit omezení zarovnání.
Více informací naleznete:
Zarovnat příklady
Definování nové typy s __declspec(align(#))
Zarovnání dat v místním úložišti podprocesů
Jak zarovnat spolupracuje s Data balení
Příklady zarovnání struktur(konkrétní x 64)
Zarovnat příklady
Následujících příkladů jak __declspec(align(#)) ovlivňuje velikost a zarovnání datových struktur.Příklady předpokládají následující definice:
#define CACHE_LINE 32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))
V následujícím příkladu S1 struktury je definována s __declspec(align(32)).Veškeré S1, zda pro definici proměnné nebo jiné prohlášení typu zajistit, aby tato data struktury 32 bajtů zarovnány.sizeof(struct S1)Vrátí 32, a S1 má následujících 16 bajtů potřebných k uložení čtyři celá čísla 16 bajtů odsazení.Každý int členem vyžaduje 4bajtové zarovnání, ale zarovnání samotné struktuře je deklarován jako 32, tak celkové zarovnání je 32.
struct CACHE_ALIGN S1 { // cache align all instances of S1
int a, b, c, d;
};
struct S1 s1; // s1 is 32-byte cache aligned
V následujícím příkladu sizeof(struct S2) vrátí 16, což je přesně součet velikostí členské protože se to stane být násobek největší zarovnání požadavku (více 8).
__declspec(align(8)) struct S2 {
int a, b, c, d;
};
V následujícím příkladu sizeof(struct S3) vrací 64.
struct S3 {
struct S1 s1; // S3 inherits cache alignment requirement
// from S1 declaration
int a; // a is now cache aligned because of s1
// 28 bytes of trailing padding
};
V následujícím příkladu, nezapomeňte, že a pouze zarovnání přírodní typu, v tomto případě 4 bajty.Však S1 musí být 32 bajtů zarovnány.Dvacet osm bajtů odsazení postupujte a, aby s1 začíná s posunem 32.S4poté zdědí zarovnání požadavek na S1, protože je největší požadavek zarovnání ve struktuře.sizeof(struct S4)Vrátí hodnotu 64.
struct S4 {
int a;
// 28 bytes padding
struct S1 s1; // S4 inherits cache alignment requirement of S1
};
Použít také následující tři deklarace proměnných __declspec(align(#)).V každém případě musí být proměnná zarovnány 32 bajtů.V případě matice, je základní adresu matice není každého člena pole zarovnání 32 bajtů.sizeof Hodnota pro každého člena pole není ovlivněno používání __declspec(align(#)).
CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;
Chcete-li zarovnat každého jednotlivého člena pole, měl být použit kód jako například:
typedef CACHE_ALIGN struct { int a; } S5;
S5 array[10];
V následujícím příkladu Poznámka: zarovnání strukturu samotného a zarovnání prvního prvku jsou shodné:
CACHE_ALIGN struct S6 {
int a;
int b;
};
struct S7 {
CACHE_ALIGN int a;
int b;
};
S6a S7 mají stejné zarovnání, přidělení a velikost vlastnosti.
V následujícím příkladu zarovnání počáteční adresy a, b, c a d jsou 4, 1, 4 a 1.
void fn() {
int a;
char b;
long c;
char d[10]
}
Pokud byla přidělena paměť haldy zarovnání závisí na funkci rozdělení, která se nazývá.Použijete-li například malloc, výsledek závisí na velikosti operand.Pokud arg > = 8, zarovnání bude 8 bajtů zarovnány.If arg < 8, zarovnání, bude první napájení 2 menší než arg.Používáte-li malloc(7), například zarovnání je 4 bajty.
Definování nové typy s __declspec(align(#))
Můžete definovat typ se zarovnání ukazatele.
Můžete například definovat struct s zarovnání hodnota takto:
struct aType {int a; int b;};
typedef __declspec(align(32)) struct aType bType;
Nyní aType a bType jsou stejné velikosti (8 bajtů), ale proměnné typu bType bude zarovnán 32 bajtů.
Zarovnání dat v místním úložišti podprocesů
Statický podproces místní úložiště (TLS) vytvořen s __declspec(thread) atributu a vložit do části TLS pracuje obraz zarovnání přesně jako normální statická data.Operační systém vytvoří TLS data přidělením dat velikost oddílu TLS a respektování atributu zarovnání oddílu TLS.
Následující příklad ukazuje různé způsoby umístění zarovnaný dat do místního úložného prostoru podprocesu.
// put an aligned integer in TLS
__declspec(thread) __declspec(align(32)) int a;
// define an aligned structure and put a variable of the struct type
// into TLS
__declspec(thread) __declspec(align(32)) struct F1 { int a; int b; } a;
// create an aligned structure
struct CACHE_ALIGN S9 {
int a;
int b;
};
// put a variable of the structure type into TLS
__declspec(thread) struct S9 a;
Jak zarovnat spolupracuje s Data balení
/Zp Volba kompilátoru a pack pragma mít vliv na data balení pro členy strukturu a unie.Tento příklad ukazuje, jak /Zp a __declspec(align(#)) společně:
struct S {
char a;
short b;
double c;
CACHE_ALIGN double d;
char e;
double f;
};
Následující tabulka uvádí posun každého člena podle různých /Zp (nebo # pragma pack) zobrazující interakci dvou hodnot.
Proměnná |
/ Zp1 |
/ Zp2 |
/ Zp4 |
/ Zp8 |
---|---|---|---|---|
a |
0 |
0 |
0 |
0 |
b |
1 |
2 |
2 |
2 |
c |
3 |
4 |
4 |
8 |
d |
32 |
32 |
32 |
32 |
e |
40 |
40 |
40 |
40 |
f |
41 |
42 |
44 |
48 |
sizeof (S) |
64 |
64 |
64 |
64 |
Další informace naleznete v tématu /ZP (Struct členské zarovnání).
Tedy posun objektu je založen na posun objektu předchozí a aktuální nastavení balení, pokud má objekt __declspec(align(#)) atribut v případě zarovnání je založeno na posun předchozí objekt a __declspec(align(#)) hodnotu pro objekt.