Allineamento (C11)

Una delle funzionalità di basso livello di C è la possibilità di specificare l'allineamento preciso degli oggetti in memoria per sfruttare al massimo i vantaggi dell'architettura hardware.

Le CPU leggono e scrivono memoria in modo più efficiente quando archiviano i dati in un indirizzo costituito da più dimensioni dei dati. Ad esempio, si accede a un intero a 4 byte in modo più efficiente se viene archiviato in un indirizzo multiplo di 4. Quando i dati non sono allineati, la CPU esegue più calcoli degli indirizzi per accedere ai dati.

Per impostazione predefinita, il compilatore allinea i dati in base alle relative dimensioni: char su un limite di 1 byte, short su un limite di 2 byte, int, longe float su un limite di 4 byte, double su un limite di 8 byte e così via.

Inoltre, allineando i dati usati di frequente alle dimensioni della riga della cache del processore, è possibile migliorare le prestazioni della cache. Si supponga, ad esempio, di definire una struttura la cui dimensione è inferiore a 32 byte. È possibile usare l'allineamento a 32 byte per garantire che tutte le istanze della struttura vengano memorizzate nella cache in modo efficiente.

In genere, non è necessario preoccuparsi dell'allineamento. Il compilatore allinea in genere i dati ai limiti naturali basati sul processore di destinazione e sulle dimensioni dei dati. I dati sono allineati fino a limiti a 4 byte su processori a 32 bit e limiti a 8 byte su processori a 64 bit. In alcuni casi, tuttavia, è possibile ottenere miglioramenti delle prestazioni o risparmi di memoria specificando un allineamento personalizzato per le strutture di dati.

Usare la parola chiave _Alignof C11 per ottenere l'allineamento preferito di un tipo o di una variabile e _Alignas per specificare un allineamento personalizzato per una variabile o un tipo definito dall'utente.

Le macro alignof di praticità e alignas, definite in <stdalign.h>, eseguono rispettivamente il mapping a _Alignof e _Alignas. Queste macro corrispondono alle parole chiave usate in C++. Pertanto, l'uso delle macro anziché delle parole chiave C può essere utile per la portabilità del codice se si condivide codice tra i due linguaggi.

alignas e _Alignas (C11)

Usare alignas o _Alignas per specificare l'allineamento personalizzato per una variabile o un tipo definito dall'utente. Possono essere applicati a uno struct, un'unione, un'enumerazione o una variabile.

Sintassi alignas

alignas(type)
alignas(constant-expression)
_Alignas(type)
_Alignas(constant-expression)

Osservazioni:

_Alignas Non può essere usato nella dichiarazione di un typedef, di un campo bit, di una funzione, di una funzione o di un oggetto dichiarato con l'identificatore register .

Specificare un allineamento che sia una potenza di due, ad esempio 1, 2, 4, 8, 16 e così via. Non usare un valore inferiore alla dimensione del tipo.

struct i tipi e union hanno un allineamento uguale all'allineamento più grande di qualsiasi membro. I byte di riempimento vengono aggiunti all'interno di per struct garantire che vengano soddisfatti i requisiti di allineamento dei singoli membri.

Se in una dichiarazione sono presenti diversi alignas identificatori, ad esempio con struct più membri con identificatori diversi alignas , l'allineamento di struct sarà almeno il valore dell'identificatore più grande.

alignas esempio

In questo esempio viene usata la macro alignof di praticità perché è portabile in C++. Il comportamento è lo stesso se si usa _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 e _Alignof (C11)

_Alignof e il relativo alias alignof restituisce l'allineamento in byte del tipo specificato. Restituisce un valore di tipo size_t.

Sintassi alignof

alignof(type)
_Alignof(type)

alignof esempio

In questo esempio viene usata la macro alignof di praticità perché è portabile in C++. Il comportamento è lo stesso se si usa _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
    */
}

Requisiti

Eseguire la compilazione con /std:c11.

Windows SDK 10.0.20348.0 (versione 2104) o versione successiva. Vedi Windows SDK per scaricare l'SDK più recente. Per istruzioni su come installare e usare l'SDK per lo sviluppo C11 e C17, vedere Installare il supporto C11 e C17 in Visual Studio.

Vedi anche

/std (Specificare la versione standard del linguaggio)
C++ alignof e alignas
Gestione del compilatore dell'allineamento dei dati