align
(C++)
In Visual Studio 2015 e versioni successive usare alignas
l'identificatore (C++11) per controllare l'allineamento. Per altre informazioni, vedere Allineamento.
Sezione specifica Microsoft
Usare __declspec(align(#))
per controllare con precisione l'allineamento dei dati definiti dall'utente (ad esempio, le allocazioni statiche o i dati automatici di una funzione).
Sintassi
__declspec( align(#) )declarator
Osservazioni:
La scrittura di applicazioni che usano le più recenti istruzioni del processore porta alla luce nuovi vincoli e problemi. Molte nuove istruzioni richiedono che i dati siano allineati ai limiti di 16 byte. L'allineamento dei dati usati di frequente alle dimensioni della riga della cache del processore migliora le prestazioni della cache. Ad esempio, se si definisce una struttura la cui dimensione è inferiore a 32 byte, è possibile che si voglia un allineamento a 32 byte per assicurarsi che gli oggetti del tipo di struttura siano memorizzati nella cache in modo efficiente.
# è il valore di allineamento. Le voci valide sono numeri interi potenze di 2, da 1 a 8192 (byte), ad esempio 2, 4, 8, 16, 32 o 64. declarator
è i dati dichiarati come allineati.
Per informazioni su come restituire un valore di tipo size_t
che rappresenta il requisito di allineamento del tipo, vedere alignof
. Per informazioni su come dichiarare puntatori non idonei quando si punta a processori a 64 bit, vedere __unaligned
.
È possibile usare __declspec(align(#))
quando si definisce un struct
oggetto , union
o class
o quando si dichiara una variabile.
Il compilatore non garantisce o tenta di mantenere l'attributo di allineamento dei dati durante un'operazione di copia o trasformazione dei dati. Ad esempio, memcpy
può copiare uno struct dichiarato con in __declspec(align(#))
qualsiasi posizione. Gli allocatori ordinari (ad esempio, malloc
, C++ operator new
e gli allocatori Win32) restituiscono in genere memoria non allineata per __declspec(align(#))
strutture o matrici di strutture. Per garantire che la destinazione di un'operazione di copia o trasformazione dati sia allineata correttamente, usare _aligned_malloc
. In alternativa, scrivere il proprio allocatore.
Non è possibile specificare l'allineamento per i parametri della funzione. Quando si passano dati con un attributo di allineamento per valore nello stack, la convenzione di chiamata ne controlla l'allineamento. Se l'allineamento dei dati è importante nella funzione chiamata, copiare il parametro nella memoria correttamente allineata prima dell'uso.
Senza __declspec(align(#))
, il compilatore allinea in genere i dati ai limiti naturali in base al processore di destinazione e alle dimensioni dei dati, fino a limiti di 4 byte su processori a 32 bit e limiti a 8 byte su processori a 64 bit. I dati nelle classi o nelle strutture sono allineati nella classe o nella struttura al minimo dell'allineamento naturale e dell'impostazione di compressione corrente (da #pragma pack
o l'opzione del /Zp
compilatore).
L'esempio seguente illustra l'uso di __declspec(align(#))
:
__declspec(align(32)) struct Str1{
int a, b, c, d, e;
};
Questo tipo ha ora un attributo di allineamento a 32 byte, Significa che tutte le istanze statiche e automatiche iniziano su un limite di 32 byte. Altri tipi di struttura dichiarati con questo tipo come membro mantengono l'attributo di allineamento di questo tipo. Ovvero, qualsiasi struttura con Str1
come elemento ha un attributo di allineamento di almeno 32.
In questo caso, sizeof(struct Str1)
è uguale a 32. Implica che se viene creata una matrice di Str1
oggetti e la base della matrice è allineata a 32 byte, anche ogni membro della matrice è allineato a 32 byte. Per creare una matrice la cui base è allineata correttamente nella memoria dinamica, usare _aligned_malloc
. In alternativa, scrivere il proprio allocatore.
Il valore di sizeof
per tutte le strutture corrisponde all'offset del membro finale più la dimensione dello stesso membro, arrotondata al multiplo più vicino del valore di allineamento del membro più grande o del valore di allineamento dell'intera struttura, a seconda di quale sia il valore più grande.
Il compilatore usa le seguenti regole per l'allineamento della struttura:
A meno che non venga sottoposto a override con
__declspec(align(#))
, l'allineamento di un membro di struttura scalare corrisponde al valore minimo della propria dimensione e della compressione corrente.A meno che non venga sottoposto a override con
__declspec(align(#))
, l'allineamento di una struttura corrisponde al valore massimo dell'allineamento dei propri membri.Un membro della struttura viene posizionato in corrispondenza di un offset dall'inizio della struttura padre, ovvero il multiplo più piccolo dell'allineamento maggiore o uguale all'offset della fine del membro precedente.
La dimensione di una struttura corrisponde al multiplo più piccolo dell'allineamento maggiore o uguale all'offset della fine dell'ultimo membro presente.
__declspec(align(#))
può solo aumentare le restrizioni di allineamento.
Per altre informazioni, vedi:
align
Esempi- Definizione di nuovi tipi con
__declspec(align(#))
- Allineamento dei dati nel Archiviazione locale del thread
- Come
align
funziona con la compressione dei dati - Esempi di allineamento della struttura x64
align
Esempi
Negli esempi seguenti viene illustrato come __declspec(align(#))
influisce sulla dimensione e sull'allineamento delle strutture di dati. Negli esempi si presuppongono le seguenti definizioni:
#define CACHE_LINE 32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))
Nell'esempio seguente, la struttura S1
viene definita con __declspec(align(32))
. Tutti gli usi di S1
per una definizione di variabile o in altre dichiarazioni dei tipi sono allineati a 32 byte. sizeof(struct S1)
restituisce 32 e S1
ha 16 byte di riempimento, coerentemente alla necessità di avere 16 byte per contenere i quattro Integer. Ogni int
membro richiede l'allineamento a 4 byte, ma l'allineamento della struttura stessa viene dichiarato come 32. Quindi l'allineamento complessivo è 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
Nell'esempio seguente, sizeof(struct S2)
restituisce 16, che corrisponde alla somma delle dimensioni del membro, visto che tale valore è un multiplo del requisito di allineamento maggiore (un multiplo di 8).
__declspec(align(8)) struct S2 {
int a, b, c, d;
};
Nell'esempio seguente, sizeof(struct S3)
restituisce 64.
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
};
Nell'esempio seguente, si noti che a
ha l'allineamento del tipo naturale, in questo caso, a 4 byte. S1
, però, deve essere allineato a 32 byte. 28 byte di riempimento seguono a
, in modo che s1
inizi all'offset 32. S4
eredita quindi il requisito di allineamento di , perché è il requisito di S1
allineamento più grande nella struttura. sizeof(struct S4)
restituisce 64.
struct S4 {
int a;
// 28 bytes padding
struct S1 s1; // S4 inherits cache alignment requirement of S1
};
Le seguenti tre dichiarazioni di variabile usano anche __declspec(align(#))
. In ogni caso, la variabile deve essere allineata a 32 byte. Nella matrice l'indirizzo di base della matrice, non ogni membro della matrice, è allineato a 32 byte. Il sizeof
valore per ogni membro della matrice non è interessato quando si usa __declspec(align(#))
.
CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;
Per allineare ogni membro di una matrice, è necessario usare un codice simile a quello indicato di seguito:
typedef CACHE_ALIGN struct { int a; } S5;
S5 array[10];
Nell'esempio seguente, si noti che l'allineamento della struttura e l'allineamento del primo elemento hanno lo stesso effetto:
CACHE_ALIGN struct S6 {
int a;
int b;
};
struct S7 {
CACHE_ALIGN int a;
int b;
};
S6
e S7
dispongono delle stesse caratteristiche di allineamento, allocazione e dimensione.
In questo esempio, l'allineamento degli indirizzi iniziali di a
, b
, c
e d
sono rispettivamente 4, 1, 4 e 1.
void fn() {
int a;
char b;
long c;
char d[10]
}
Se la memoria viene allocata nell'heap, l'allineamento dipende dalla funzione di allocazione che viene chiamata. Ad esempio, se si usa malloc
, il risultato dipende dalla dimensione dell'operando. Se arg>= 8, la memoria restituita è allineata a 8 byte. Se arg< 8, l'allineamento della memoria restituita è la prima potenza di 2 minore di arg. Ad esempio, se si usa malloc(7)
, l'allineamento è di 4 byte.
Definizione di nuovi tipi con __declspec(align(#))
È possibile definire un tipo con una caratteristica di allineamento.
Ad esempio, è possibile definire un struct
oggetto con un valore di allineamento in questo modo:
struct aType {int a; int b;};
typedef __declspec(align(32)) struct aType bType;
aType
Ora e bType
hanno le stesse dimensioni (8 byte), ma le variabili di tipo bType
sono allineate a 32 byte.
Allineamento dei dati nell'archiviazione locale del thread
L'archiviazione locale di thread (TLS, Thread-Local Storage) statici creata con l'attributo __declspec(thread)
e inserita nella sezione TLS dell'immagine funziona per l'allineamento esattamente come i dati statici normali. Per creare dati TLS, il sistema operativo alloca memoria con la stessa dimensione della sezione TLS e rispetta l'attributo di allineamento della sezione TLS.
L'esempio seguente illustra vari modi per inserire i dati allineati nell'archiviazione locale dei thread.
// 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;
Come align
funziona con la compressione dei dati
L'opzione /Zp
del compilatore e il pack
pragma hanno l'effetto della compressione dei dati per i membri della struttura e dell'unione. Questo esempio mostra come /Zp
e __declspec(align(#))
lavorare insieme:
struct S {
char a;
short b;
double c;
CACHE_ALIGN double d;
char e;
double f;
};
Nella tabella seguente viene elencato l'offset di ogni membro con valori diversi /Zp
(o #pragma pack
) che illustrano l'interazione tra i due membri.
Variabile | /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 |
Per altre informazioni, vedere (Allineamento membri struct).For more information, see /Zp
(Struct Member Alignment).
L'offset di un oggetto è basato sull'offset tra l'oggetto precedente e l'impostazione di compressione corrente, a meno che l'oggetto non abbia un attributo __declspec(align(#))
. In quest'ultimo caso, l'allineamento è basato sull'offset tra l'oggetto precedente e il valore __declspec(align(#))
dell'oggetto.
Fine sezione specifica Microsoft
Vedi anche
__declspec
Panoramica delle convenzioni ABI ARM
Convenzioni del software x64
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per