Alignement (C11)
Une des fonctionnalités de bas niveau de C est la possibilité de spécifier avec précision l’alignement des objets en mémoire afin d’exploiter au mieux les capacités d’une architecture matérielle spécifique.
Les processeurs lisent et écrivent de la mémoire plus efficacement lorsqu’ils stockent des données à une adresse qui est un multiple de la taille des données. Par exemple, un entier de 4 octets est accessible plus efficacement s’il est stocké à une adresse multiple de 4. Lorsque des données ne sont pas alignées, le processeur effectue davantage de calcul d’adresse pour accéder aux données.
Par défaut, le compilateur aligne les données en fonction de leur taille : char
sur une limite de 1 octet, short
sur une limite de 2 octets, int
, long
et float
sur une limite de 4 octets, double
sur une limite de 8 octets, et ainsi de suite.
En outre, en alignant les données fréquemment utilisées avec la taille de ligne de cache du processeur, vous pouvez améliorer les performances du cache. Par exemple, supposons que vous définissez une structure dont la taille est inférieure à 32 octets. Vous pouvez utiliser l’alignement de 32 octets pour vous assurer que toutes les instances de la structure sont mises en cache efficacement.
En règle générale, vous n’avez pas besoin de vous soucier de l’alignement. Le compilateur aligne généralement les données sur des limites naturelles basées sur le processeur cible et la taille des données. Les données sont alignées jusqu’à 4 octets sur des processeurs 32 bits, et les limites de 8 octets sur des processeurs 64 bits. Dans certains cas toutefois, vous pouvez obtenir des améliorations de performances ou des économies de mémoire en spécifiant un alignement personnalisé pour vos structures de données.
Utilisez le mot clé C11 _Alignof
pour obtenir l’alignement préféré d’un type ou d’une variable, et _Alignas
pour spécifier un alignement personnalisé pour une variable ou un type défini par l’utilisateur.
Les macros de commodité alignof
et alignas
, définies dans <stdalign.h>
, correspondent directement respectivement à _Alignof
et _Alignas
. Ces macros correspondent aux mots clés utilisés en C++. Par conséquent, l’utilisation des macros au lieu des mots clés C peut être utile pour la portabilité du code si vous partagez du code entre les deux langages.
alignas
et _Alignas
(C11)
Utilisez alignas
ou _Alignas
pour spécifier un alignement personnalisé pour une variable ou un type défini par l’utilisateur. Elles peuvent être appliquées à un struct, une union, une énumération ou une variable.
Syntaxe de alignas
alignas(type)
alignas(constant-expression)
_Alignas(type)
_Alignas(constant-expression)
Notes
_Alignas
ne peut pas être utilisé dans la déclaration d’une typedef, d’un champ de bits, d’une fonction, d’un paramètre de fonction ou d’un objet déclaré avec le spécificateur register
.
Spécifiez un alignement qui est une puissance de deux, comme 1, 2, 4, 8, 16, etc. N’utilisez pas de valeur inférieure à la taille du type.
Les types struct
et union
types ont un alignement égal à l’alignement le plus important de n’importe quel membre. Des octets de remplissage sont ajoutés dans un struct
pour s’assurer que les exigences d’alignement de membres individuels sont remplies.
S’il existe plusieurs spécificateurs alignas
dans une déclaration (par exemple, un struct
avec plusieurs membres qui ont des spécificateurs alignas
différents), l’alignement du struct
est au moins de la valeur du spécificateur le plus grand.
Exemple alignas
Cet exemple utilise la macro de commodité alignof
, car elle est portable vers C++. Le comportement est le même si vous utilisez _Alignof
.
// Compile with /std:c11
#include <stdio.h>
#include <stdalign.h>
typedef struct
{
int value; // aligns on a 4-byte boundary. There will be 28 bytes of padding between value and alignas
alignas(32) char alignedMemory[32]; // assuming a 32 byte friendly cache alignment
} cacheFriendly; // this struct will be 32-byte aligned because alignedMemory is 32-byte aligned and is the largest alignment specified in the struct
int main()
{
printf("sizeof(cacheFriendly): %d\n", sizeof(cacheFriendly)); // 4 bytes for int value + 32 bytes for alignedMemory[] + padding to ensure alignment
printf("alignof(cacheFriendly): %d\n", alignof(cacheFriendly)); // 32 because alignedMemory[] is aligned on a 32-byte boundary
/* output
sizeof(cacheFriendly): 64
alignof(cacheFriendly): 32
*/
}
alignof
et _Alignof
(C11)
_Alignof
et son alias alignof
retournent l’alignement en octets du type spécifié. Ils retournent une valeur de type size_t
.
Syntaxe de alignof
alignof(type)
_Alignof(type)
Exemple alignof
Cet exemple utilise la macro de commodité alignof
, car elle est portable vers C++. Le comportement est le même si vous utilisez _Alignof
.
// Compile with /std:c11
#include <stdalign.h>
#include <stdio.h>
int main()
{
size_t alignment = alignof(short);
printf("alignof(short) = %d\n", alignment); // 2
printf("alignof(int) = %d\n", alignof(int)); // 4
printf("alignof(long) = %d\n", alignof(long)); // 4
printf("alignof(float) = %d\n", alignof(float)); // 4
printf("alignof(double) = %d\n", alignof(double)); // 8
typedef struct
{
int a;
double b;
} test;
printf("alignof(test) = %d\n", alignof(test)); // 8 because that is the alignment of the largest element in the structure
/* output
alignof(short) = 2
alignof(int) = 4
alignof(long) = 4
alignof(float) = 4
alignof(double) = 8
alignof(test) = 8
*/
}
Spécifications
Compilez avec /std:c11
.
SDK Windows 10.0.20348.0 (version 2104) ou ultérieure. Pour télécharger le Kit de développement logiciel (SDK) le plus récent, consultez SDK Windows. Pour obtenir des instructions sur l’installation et l’utilisation du Kit de développement logiciel (SDK) pour le développement en C11 et C17, consultez Installer la prise en charge de C11 et C17 dans Visual Studio.
Voir aussi
/std
(Spécifier la version du standard du langage)
C++ alignof
et alignas
Gestion par le compilateur de l’alignement des données