Allineamento
Una delle funzionalità di basso livello di C++ è costituita dalla possibilità di specificare l'allineamento preciso degli oggetti in memoria per sfruttare al massimo una specifica architettura hardware. Per impostazione predefinita, il compilatore allinea i membri di classe e struct sul valore delle dimensioni: bool
e char
sui limiti a 1 byte, short
su limiti a 2 byte, int
, long
e float
su limiti a 4 byte e , double
e long long
long double
su limiti a 8 byte.
Nella maggior parte degli scenari, non è mai necessario preoccuparsi dell'allineamento perché l'allineamento predefinito è già ottimale. In alcuni casi, tuttavia, è possibile ottenere miglioramenti significativi delle prestazioni o risparmi di memoria specificando un allineamento personalizzato per le strutture di dati. Prima di Visual Studio 2015 è possibile usare le parole chiave __alignof
specifiche di Microsoft e __declspec(align)
specificare un allineamento maggiore del valore predefinito. A partire da Visual Studio 2015 è consigliabile usare le parole chiave alignof
standard C++11 e alignas
per ottenere la massima portabilità del codice. Le nuove parole chiave si comportano nello stesso modo delle estensioni specifiche di Microsoft. La documentazione per tali estensioni si applica anche alle nuove parole chiave. Per altre informazioni, vedere alignof
Operatore, alignas
identificatore e allineamento. Lo standard C++ non specifica il comportamento di compressione per l'allineamento sui limiti inferiori al valore predefinito del compilatore per la piattaforma di destinazione, quindi è comunque necessario usare Microsoft #pragma pack
in questo caso.
Usare la classe aligned_storage per l'allocazione di memoria delle strutture di dati con allineamenti personalizzati. La classe aligned_union consente di specificare l'allineamento per le unioni con costruttori o distruttori nontriviali.
Allineamento e indirizzi di memoria
Per allineamento si intende una proprietà di un indirizzo di memoria, espresso come modulo di indirizzo numerico di una potenza di 2. Ad esempio, l'indirizzo 0x0001103F modulo 4 è 3. Questo indirizzo viene detto essere allineato a 4n+3, dove 4 indica la potenza scelta di 2. L'allineamento di un indirizzo dipende dalla potenza scelta di 2. Il modulo 8 dello stesso indirizzo è 7. Si dice che un indirizzo è allineato a X se il relativo allineamento è Xn+0.
Le CPU eseguono istruzioni che operano sui dati archiviati in memoria. I dati vengono identificati dagli indirizzi in memoria. Un singolo datum ha anche una dimensione. Viene chiamato un datum allineato naturalmente se l'indirizzo è allineato alle dimensioni. In caso contrario, viene chiamato non allineato . Ad esempio, un datum a virgola mobile a 8 byte viene allineato naturalmente se l'indirizzo usato per identificarlo ha un allineamento a 8 byte.
Gestione del compilatore dell'allineamento dei dati
I compilatori tentano di eseguire allocazioni di dati in modo da impedire il disallineamento dei dati.
Per i tipi di dati semplici il compilatore assegna indirizzi che sono multipli delle dimensioni in byte del tipo di dati. Ad esempio, il compilatore assegna indirizzi a variabili di tipo long
multiple pari a 4, impostando i 2 bit inferiori dell'indirizzo su zero.
Il compilatore riempie anche le strutture in modo da allineare naturalmente ogni elemento della struttura. Si consideri la struttura struct x_
nell'esempio di codice seguente:
struct x_
{
char a; // 1 byte
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
} bar[3];
Il compilatore aggiunge elementi di spaziatura interna in questa struttura in modo applicare naturalmente l'allineamento.
Nell'esempio di codice seguente viene illustrato come il compilatore inserisce la struttura riempita in memoria:
// Shows the actual memory layout
struct x_
{
char a; // 1 byte
char _pad0[3]; // padding to put 'b' on 4-byte boundary
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
char _pad1[1]; // padding to make sizeof(x_) multiple of 4
} bar[3];
Entrambe le dichiarazioni restituiscono sizeof(struct x_)
12 byte.
La seconda dichiarazione include due elementi di spaziatura interna:
char _pad0[3]
per allineare ilint b
membro su un limite di 4 byte.char _pad1[1]
per allineare gli elementi della matrice della strutturastruct _x bar[3];
su un limite a 4 byte.
La spaziatura interna allinea gli elementi di bar[3]
in modo da consentire l'accesso naturale.
L'esempio di codice seguente illustra il layout della bar[3]
matrice:
adr offset element
------ -------
0x0000 char a; // bar[0]
0x0001 char pad0[3];
0x0004 int b;
0x0008 short c;
0x000a char d;
0x000b char _pad1[1];
0x000c char a; // bar[1]
0x000d char _pad0[3];
0x0010 int b;
0x0014 short c;
0x0016 char d;
0x0017 char _pad1[1];
0x0018 char a; // bar[2]
0x0019 char _pad0[3];
0x001c int b;
0x0020 short c;
0x0022 char d;
0x0023 char _pad1[1];
alignof
e alignas
L'identificatore alignas
è un modo standard C++ portabile per specificare l'allineamento personalizzato di variabili e tipi definiti dall'utente. L'operatore alignof
è analogamente un modo portabile e standard per ottenere l'allineamento di un tipo o di una variabile specificata.
Esempio
È possibile usare alignas
in una classe, uno struct o un'unione o su singoli membri. Quando vengono rilevati più alignas
identificatori, il compilatore sceglie quello con il valore più grande.
// alignas_alignof.cpp
// compile with: cl /EHsc alignas_alignof.cpp
#include <iostream>
struct alignas(16) Bar
{
int i; // 4 bytes
int n; // 4 bytes
alignas(4) char arr[3];
short s; // 2 bytes
};
int main()
{
std::cout << alignof(Bar) << std::endl; // output: 16
}
Vedi anche
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