Sdílet prostřednictvím


align (C++)

Specifické pro Microsoft

Použití __declspec(align(#)) přesně řídit zarovnání uživatelská data (například statický přidělení nebo automatické dat ve funkci).

__declspec( align( # ) ) declarator

Poznámky

Psaní aplikací, které používají nejnovější procesoru pokynů, které zavádí některé nové omezení a problémy.Mnoho nových pokyny klást musí mít data uspořádána hranice 16 bajtů.Kromě toho zarovnáním často používané data, která mají velikost mezipaměti řádku specifické procesory zlepšit výkon mezipaměti.Například pokud definujete struktury, jejichž velikost je menší než 32 bajtů, můžete ho zarovnat k 32 bajtů, abyste měli jistotu, že objekty tohoto typu struktury jsou efektivní uloženy v mezipaměti.

# je hodnota zarovnání.Platná zadání jsou pravomocí celé číslo od 1 do 8192 (v bajtech), například 2, 4, 8, 16, 32 nebo 64.declaratorjsou data, která definujete jako zarovnán.

Informace o tom, jak vrátit hodnotu typu size_t , je požadavek na zarovnání typu naleznete v tématu __alignof.Informace o tom, jak deklarovat nezarovnané ukazatele, pokud je zaměření na 64bitové procesory naleznete v tématu __unaligned.

Můžete použít __declspec(align(#)) při definování struct, union, nebo class, nebo pokud deklarujete proměnnou.

Kompilátor nezahrnuje zaručit a pokuste se zachovat atribut zarovnání dat během transformace operace kopírování nebo data.Můžete například memcpy můžete zkopírovat struktura deklarována s __declspec(align(#)) na libovolné místo.Všimněte si, že běžný allocators – například přidělit, C++ operátor novéa Win32 allocators – vrácení paměti, která není dostatečně zarovnán obvykle pro __declspec(align(#)) struktury nebo pole struktur.Chcete-li zaručit, aby je cíl operace kopírování nebo data transformaci správně zarovnán, použijte _aligned_malloc, nebo napsat vlastní přidělení.

Nelze určit vyrovnání parametry funkce.Data, která má atribut zarovnání je předán podle hodnoty v zásobníku jeho zarovnání je řízeno konvence volání.Pokud je důležité pro volané funkce zarovnání dat, zkopírujte do paměti, správně zarovnané před použitím parametru.

Bez __declspec(align(#)), Visual C++ obecně Zarovná data ve fyzické hranice na základě cílový procesor a velikost dat, až do 4 bajtů hranice 32bitové procesory a 8-byte hranice na 64bitové procesory.Data v třídy nebo struktury je zarovnán v dané třídě nebo struktuře minimálně na jeho fyzické zarovnání a aktuální nastavení balení (z #pragma pack nebo /Zp možnosti kompilátoru).

Tento příklad ukazuje použití __declspec(align(#)):

__declspec(align(32)) struct Str1{
   int a, b, c, d, e;
};

Tento typ nyní obsahuje atribut zarovnání 32 bajtů.To znamená, že všechny instance statický a automatického spuštění na hranici 32 bajtů.Další strukturovaného typu deklarován s tímto typem jako člen zachovat tento typ atributu zarovnání, to znamená, že existuje struktury pomocí Str1 jako element bude mít atribut zarovnání alespoň 32.

Všimněte si, že sizeof(struct Str1) rovná 32.To znamená, že pokud je vytvořen pole objektů Str1 a základní pole je 32 bajtů zarovnán, každého člena pole je také zarovnán 32 bajtů.Chcete-li vytvořit pole, jejichž základem je správně zarovnán v dynamické paměti, použijte _aligned_malloc, nebo napsat vlastní přidělení.

sizeof Žádnou strukturu hodnotu Posun posledního člena plus velikost tohoto člena, zaokrouhleny nahoru na nejbližší násobek největší hodnotu zarovnání člen nebo hodnota zarovnání celá struktura, podle toho, která je větší.

Kompilátor používá pro zarovnání struktury následujícími pravidly:

  • Pokud přepsána s __declspec(align(#)), zarovnání člena skalární struktury je minimální velikost a aktuální balení.

  • Pokud přepsána s __declspec(align(#)), zarovnání struktury, je maximální počet jednotlivých zarovnání z její členy.

  • Člen struktury je umístěn na posun od začátku jeho nadřazená struktura, což je nejmenší násobkem svého zarovnání větší než nebo rovna hodnotě Posun konci předchozího člena.

  • Velikost struktury je nejmenší násobkem svého zarovnání větší než nebo rovna hodnotě Posun konce jeho posledního člena.

__declspec(align(#))zvýšíte pouze omezení zarovnání.

Další informace naleznete v tématu:

  • Zarovnat příklady

  • Definování nových typů s __declspec(align(#))

  • Zarovnání dat v místním úložišti podprocesů

  • Jak zarovnat pracuje s balení dat

  • Příklady zarovnání struktur(x 64 konkrétní)

Zarovnat příklady

Následující příklady zobrazit jak __declspec(align(#)) ovlivňuje velikost a zarovnání datových struktur.Příklady předpokládat, že tyto definice:

#define CACHE_LINE  32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))

V tomto příkladu S1 struktury je definován pomocí __declspec(align(32)).Všechna použití S1 pro definici proměnné nebo do jiného typu deklarace proměnných je zarovnán 32 bajtů.sizeof(struct S1)Vrátí 32, a S1 má 16 bajtů odsazení následující 16 bajtů potřebných k uložení čtyři celá čísla.Každý int člena vyžaduje zarovnání 4 bajtů, ale zarovnání strukturu samotného je deklarován jako 32.Celkové zarovnání tedy 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 tomto příkladu sizeof(struct S2) vrátí hodnotu 16, které je právě součet velikostí člena, protože se jedná násobek největší požadavek zarovnání (násobek 8).

__declspec(align(8)) struct S2 {
   int a, b, c, d;
};

V následujícím příkladu sizeof(struct S3) vrátí 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 tomto příkladu Všimněte si, že a má zarovnání fyzické typu, v tomto případě 4 bajty.Však S1 musí být 32 bajtů zarovnáno.Dvacet osm bajtů odsazení podle atak, aby s1 začíná posunu 32.S4potom dědí požadavek na zarovnání S1, protože je požadavek na největší zarovnání ve struktuře.sizeof(struct S4)Vrátí 64.

struct S4 {
   int a;
   // 28 bytes padding
    struct S1 s1;      // S4 inherits cache alignment requirement of S1
};

Následující tři deklarace proměnných také použít __declspec(align(#)).V každém případě proměnná musí být zarovnáno 32 bajtů.V případě pole základní adresu pole není každého člena pole je zarovnán podle 32 bajtů.sizeof Hodnoty pro každého člena pole není ovlivněny při použití __declspec(align(#)).

CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;

Chcete-li zarovnat každého člena pole, by měl použít kód, například:

typedef CACHE_ALIGN struct { int a; } S5;
S5 array[10];

V tomto příkladu Všimněte si, že vyrovnání strukturu samotného a vyrovnání prvním elementem mají stejný účinek:

CACHE_ALIGN struct S6 {
   int a;
   int b;
};

struct S7 {
   CACHE_ALIGN int a;
               int b;
};

S6a S7 mít identické zarovnání, přidělení a velikost vlastnosti.

V tomto příkladu zarovnání počáteční adresy a, b c a d jsou 4, 1, 4 a 1, v uvedeném pořadí.

void fn() { 
   int a;
   char b;
   long c;
   char d[10]
} 

Zarovnání při přidělení paměti do haldy závisí na funkci přidělení, která je volána.Pokud použijete například malloc, výsledek závisí na velikosti operand.Pokud argument > = 8, paměť vrátil je zarovnán 8 bajtů.Pokud argument < 8, zarovnání paměti vrácená je první mocninu dvou menší než argument.Pokud používáte malloc(7), například zarovnání je 4 bajty.

Definování nových typů s __declspec(align(#))

Můžete definovat typ se zarovnání charakteristiku.

Například můžete definovat struct s zarovnání hodnota takto:

struct aType {int a; int b;};
typedef __declspec(align(32)) struct aType bType;

Nyní si 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é místní úložiště (TLS) vytvořen s __declspec(thread) atribut a vložit do části TLS děl obrázek pro zarovnání stejně jako normální statickým datům.Chcete-li vytvořit TLS data, operační systém přiděluje paměť velikost oddílu TLS a respektuje atribut zarovnání oddílu TLS.

Tento příklad ukazuje různé způsoby, jak umístění zarovnanými dat do místního úložiště vlákna.

// 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 pracuje s balení dat

/Zp Možnosti kompilátoru a pack pragma mít za následek balení dat pro strukturu a unie členy.Tento příklad ukazuje, jak /Zp a __declspec(align(#)) vzájemně spolupracují:

struct S {
   char a;
   short b;
   double c;
   CACHE_ALIGN double d;
   char e;
   double f;
};

V následující tabulce jsou uvedeny posun každého člena v rámci různých /Zp (nebo #pragma pack) hodnot, zobrazující interakci dva.

Proměnná

/ Zp1

/ Zp2

/ Zp4

/ Zp8

na

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 (zarovnání členů struktury).

Posun objektu je založena na posun předchozí objektu a aktuální nastavení balení, pokud objekt má __declspec(align(#)) atribut v takovém případě zarovnání je založeno na posun předchozí objekt a __declspec(align(#)) hodnotu objektu.

Viz také

Referenční dokumentace

__declspec

Koncepty

Overview of ARM ABI Conventions

Přehled x64 konvencí volání