align (C++)

Spécifique à Microsoft

Utilisez __declspec(align(#)) pour contrôler avec précision l'alignement des données définies par l'utilisateur (par exemple, les allocations statiques ou des données automatiques dans une fonction).

Pour plus d'informations sur l'inscription, consultez Windows Data Alignment on IPF, x86, and x64.

__declspec( align( # ) ) declarator

Notes

Les applications d'écriture qui utilisent la dernière instruction de processeur introduit de nouveaux contraintes et problèmes.En particulier, de nombreux nouvelle instruction requiert que les données doivent être alignées sur des limites de 16 octets.En outre, en alignant fréquemment des données utilisée à la taille de ligne de cache d'un processeur particulier, vous améliorez la performance du cache.Par exemple, si vous définissez une structure dont la taille est inférieure à 32 octets, vous pouvez souhaiter l'aligner sur 32 octets pour garantir que les objets de ce type de structure sont efficacement mis en cache.

# est la valeur d'inscription.Les entrées valides sont des puissances de deux entiers de 1 à 8192 (en octets), telle que 2, 4, 8, 16, 32, ou 64.declarator est les données que vous déclarez comme aligné.

Consultez __alignof pour plus d'informations sur la manière de retourner une valeur du type size_t qui est la spécification d'alignement du type.et __unaligned pour plus d'informations sur la manière de déclarer les pointeurs non alignés lorsque vous ciblez des processeur 64 bits.

Vous pouvez utiliser __declspec(align(#)) lorsque vous définissez struct, union, ou class, ou lorsque vous déclarez une variable.

Sans __declspec(align(#)), Visual C++ aligne les données sur des limites naturelles selon la taille des données, par exemple 4 entiers d'octets sur des limites de 4 octets et 8 doubles d'octets sur des limites de 8 octets.Les données dans les classes ou structures sont alignées dans la classe ou la structure au minimum de son alignement naturel et du paramètre actuel d'encapsulation (#pragma pack ou de l'option du compilateur pour /Zp ).

Vous ne pouvez pas spécifier l'alignement pour les paramètres de fonction.

Par exemple :

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

Ce type a maintenant un attribut de 32 inscriptions des octets, ce qui signifie que toutes les instances doivent commencer à la limite d'octets 32.Les types supplémentaires de structure déclarés avec ce type comme conserve membre cet attribut de l'alignement du type, c. autrement dit., toute structure avec Str1 comme élément auront un attribut d'inscription d'au moins 32.

En résumé :

  • À moins que substitué par __declspec(align(#)), l'inscription d'un membre de structure scalaire est le minimum de sa taille et de la compression actuel.

  • À moins que substitué par __declspec(align(#)), l'inscription d'une structure est la valeur maximale des différents inscriptions de ses membres.

  • Un membre de structure est placé à un offset du début de sa structure parente qui est le plus petit multiple de son alignement supérieur ou égal à l'offset de la fin de le membre précédent.

  • La taille d'une structure est le plus petit multiple de son plus grand supérieure ou égale d'alignement l'offset de la fin de son dernier membre.

Notez qu' sizeof(struct Str1) est égal à 32, de sorte que, si un tableau d'objets Str1 est créé, et la base du tableau est l'octet 32 aligné, puis chaque membre du tableau sont également l'octet 32 aligné.Pour créer un tableau dont la base est alignée correctement, utilisez _aligned_malloc, ou écrivez votre propre allocateur.Notez que les allocateurs normaux, tels que malloc, C++ operator new, et les allocateurs Win32 retournent la mémoire qui très probablement ne sera pas suffisamment alignée pour les structures dedeclspec(align(#)) ou les tableaux de structures.

La valeur d' sizeof pour toute structure est l'offset du membre final, plus la taille de ce membre, arrondie jusqu'à plusieurs le plus proche de la plus grande valeur membre d'alignement ou de la valeur d'alignement de la structure entière, celui qui est supérieur.

__declspec(align(#)) peut uniquement augmenter les restrictions d'inscription.

Pour plus d'informations, consultez :

  • aligner les exemples

  • Définissant de nouveaux types avec __declspec (align (#))

  • aligner des données dans le stockage local des threads

  • Comment aligner fonctionne avec l'encapsulation de données

  • Examples of Structure Alignment (spécifique à x64)

aligner les exemples

Le les exemples suivants indiquent comment __declspec(align(#)) affecte la taille et l'alignement des structures de données.les exemples supposent les définitions suivantes :

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

dans l'exemple suivant, la structure d' S1 est définie avec __declspec(align(32)).Toutes les utilisations d' S1, si pour une définition de variable ou d'autres déclarations de type, vérifiez que ces données de structure est l'octet 32 aligné.sizeof(struct S1) retourne 32, et S1 a 16 octets de remplissage après les 16 octets requis pour gérer les quatre entiers.Chaque membre d' int nécessite l'inscription d'octets 4, mais l'alignement de la structure lui-même est déclaré comme étant 32, donc l'alignement global est 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

Dans l'exemple suivant, sizeof(struct S2) retourne 16, qui est exactement la somme des tailles membres, car il est un multiple de la plus grande spécification d'inscription (un multiple de 8).

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

Dans l'exemple suivant, retourne 64 d' sizeof(struct S3) .

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
};

Dans l'exemple suivant, notez qu' a a uniquement l'alignement du type natif, dans ce cas, 4 octets.Toutefois, S1 doit être l'octet 32 aligné.Vingt-huit octets de remplissage suivent a, afin que d' s1 au décalage 32.S4 hérite ensuite la spécification d'alignement de S1, car il s'agit de la plus grande spécification d'alignement de la structure.retourne 64 d'sizeof(struct S4) .

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

Les trois déclarations de variables suivantes utilisent également __declspec(align(#)).dans chaque cas, la variable doit être l'octet 32 aligné.Dans le cas de le tableau, l'adresse de base du tableau, non chaque membre du groupe, est l'octet 32 aligné.La valeur d' sizeof pour chaque membre du groupe n'est pas affectée par l'utilisation __declspec(align(#)).

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

Pour aligner chaque membre individuel d'un tableau, le code tel que le suivant doit être utilisé :

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

Dans l'exemple suivant, notez que aligne la structure elle-même et en alignant le premier élément et sont identiques :

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

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

S6 et S7 ont l'alignement, l'allocation, et les caractéristiques identiques de taille.

Dans l'exemple suivant, l'alignement des adresses de début d'a, b, c, d et sont 4, 1, 4, et 1, respectivement.

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

L'inscription si la mémoire sont alloués sur le tas dépend de la fonction d'allocation est appelée.par exemple, si vous utilisez malloc, le résultat dépend de la taille d'opérande.Si arg >= 8, l'alignement est l'octet 8 aligné.Si arg < 8, l'alignement est la première puissance de 2 moins qu' arg.Par exemple, si vous utilisez malloc (7), l'alignement est de 4 octets.

Définissant de nouveaux types avec __declspec (align (#))

Vous pouvez définir un type avec une caractéristique d'inscription.

Par exemple, vous pouvez définir structavec une valeur d'inscription comme suit :

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

Maintenant, aType et bType sont la même taille (8 octets) mais les variables de type bType seront l'octet 32 aligné.

aligner des données dans le stockage local des threads

Le stockage local des threads de type statique (TLS) créé avec l'attribut d' __declspec(thread) et placé dans la section TLS dans l'image fonctionne pour l'inscription exactement à appeler des données statiques normales.Le système d'exploitation crée des données TLS en allouant des données la taille de la section de transport et en respectant l'attribut d'alignement de section TLS.

L'exemple suivant montre différentes manières de placer des données alignées dans le stockage local des threads.

// 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;

Comment aligner fonctionne avec l'encapsulation de données

L'option du compilateur pour /Zp et le pragma d' pack ont l'effet des données de compactage pour la structure et les membres d'union.cet exemple montre comment /Zp et __declspec(align(#)) fonctionnent ensemble :

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

Le tableau suivant répertorie le décalage de chaque membre sous diverses valeurs d' /Zp (ou #pragma pack), montrant comment les deux interactifs.

Variable

/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

Pour plus d'informations, consultez /Zp (Alignement des membres de la structure).

Par conséquent, l'offset d'un objet est basé sur l'offset de l'objet précédent et du paramètre actuel de compactage, à moins que l'objet a un attribut d' __declspec(align(#)) , auquel cas l'alignement est basé sur l'offset de l'ancien objet et la valeur d' __declspec(align(#))pour l'objet.

Voir aussi

Référence

__declspec