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
, long
e 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