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