Alinhar (C++)
Específicos do Microsoft
Use __declspec(align(#)) para controlar com precisão o alinhamento dos dados definidos pelo usuário (por exemplo, alocações estáticas ou automática de dados em uma função).
Para obter mais informações sobre o alinhamento, consulte Alinhamento de dados do Windows no IPF, x86, e em x64.
__declspec( align( # ) ) declarator
Comentários
Gravar aplicativos que utilizam as instruções mais recentes do processador introduz algumas novas restrições e problemas.Em particular, muitas novas instruções requerem que dados devem ser alinhados em limites de 16 bytes.Além disso, alinhando os dados usados com freqüência para o tamanho da linha de cache de um processador específico, melhorar o desempenho de cache.Por exemplo, se você definir uma estrutura cujo tamanho é menor que 32 bytes, convém para alinhá-lo para 32 bytes para garantir que os objetos desse tipo de estrutura eficiente são armazenados em cache.
# é o valor de alinhamento.As entradas válidas são potências de número inteiro de dois a partir de 1 8192 (bytes), como, por exemplo, 2, 4, 8, 16, 32 ou 64.declaratorsão os dados que você estiver declarando alinhada.
Consulte __alignof para obter informações sobre como retornar um valor do tipo size_t isto é o requisito de alinhamento do tipo.e __unaligned para obter informações sobre como declarar os ponteiros não alinhados ao direcionamento processadores de 64 bits.
Você pode usar __declspec(align(#)) quando você define uma struct, union, ou class, ou quando você declara uma variável.
Sem __declspec(align(#)), Visual C++ alinha os dados em limites naturais, com base no tamanho dos dados, inteiros de 4 bytes por exemplo nos limites de 4 bytes e duplicatas em limites de 8 bytes de 8 bytes.Dados em classes ou estruturas são alinhados dentro da classe ou estrutura, no mínimo de seu alinhamento natural e a configuração atual de embalagem (de # pragma pack ou o /Zp opção de compilador).
Não é possível especificar o alinhamento para os parâmetros da função.
Por exemplo:
__declspec(align(32)) struct Str1{
int a, b, c, d, e;
};
Esse tipo agora tem um atributo de alinhamento de 32 bytes, o que significa que todas as instâncias devem iniciar em um limite de 32 bytes.Os tipos de estrutura adicional declarados com esse tipo como um membro preservar o atributo de alinhamento desse tipo, ou seja, qualquer estrutura de com Str1 como um elemento terão um atributo de alinhamento pelo menos 32.
Para resumir:
A menos que substituída com __declspec(align(#)), o alinhamento de um membro da estrutura de escalar é o mínimo de seu tamanho e de remessa atual.
A menos que substituída com __declspec(align(#)), o alinhamento de uma estrutura é o máximo dos alinhamentos individuais de seus membros.
Um membro da estrutura é colocado em um deslocamento do início de sua estrutura de pai que é o menor múltiplo de seu alinhamento maior ou igual ao deslocamento do final do membro anterior.
O tamanho de uma estrutura é o menor múltiplo de seu alinhamento maior maior que ou igual ao deslocamento do final de seu último membro.
Observe que sizeof(struct Str1) é igual a 32, de modo que, se uma matriz de objetos Str1 é criada e a base da matriz é 32 bytes alinhadas, em seguida, cada membro da matriz também será alinhado 32 bytes.Para criar uma matriz cuja base está alinhado corretamente, use _aligned_malloc, ou escreve seu próprios alocador.Observe que o normal allocators, como malloc, C++ novo operador, e os allocators Win32 retornam a memória que será provavelmente não suficientemente alinhada para **_ _**declspec(align(#)) estruturas ou matrizes de estruturas.
O sizeof valor para qualquer estrutura é o deslocamento, o membro final, mais o tamanho desse membro, arredondado para o próximo múltiplo o maior valor de alinhamento de membro ou o valor de alinhamento de toda a estrutura, o que for maior.
__declspec(align(#))só pode aumentar as restrições de alinhamento.
Para obter mais informações, consulte:
Exemplos de alinhar
Definindo novos tipos de __declspec(align(#))
Alinhamento de dados no armazenamento Local de segmento
Como alinhar funciona com dados de remessa
Exemplos de alinhamento estrutura(x64 específicos)
Exemplos de alinhar
Os exemplos a seguir mostram como __declspec(align(#)) afeta o tamanho e alinhamento das estruturas de dados.Os exemplos assumem as seguintes definições:
#define CACHE_LINE 32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))
No exemplo a seguir, o S1 estrutura é definida com __declspec(align(32)).Todos os usos de S1, se alinhados para uma definição de variável ou outras declarações de tipo, certifique-se de que esses dados de estrutura são 32 bytes.sizeof(struct S1)Retorna a 32, e S1 tem 16 bytes de preenchimento seguindo os 16 bytes necessários para manter os quatro inteiros.Cada int membro requer o alinhamento de 4 bytes, mas o alinhamento da estrutura em si está declarado como 32, portanto, o alinhamento geral é 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
No exemplo a seguir, sizeof(struct S2) retornará 16, que é exatamente a soma dos tamanhos de membro, pois isso pode acontecer de ser um múltiplo da maior exigência de alinhamento (um múltiplo de 8).
__declspec(align(8)) struct S2 {
int a, b, c, d;
};
No exemplo a seguir, sizeof(struct S3) retorna 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
};
No exemplo a seguir, observe que a tem somente o alinhamento da natural tipo, nesse caso, 4 bytes.No entanto, S1 devem estar 32 bytes alinhado.Vinte e oito bytes de preenchimento siga a, de modo que s1 inicia no deslocamento de 32.S4em seguida, herda o requisito de alinhamento de S1, porque ela é a maior necessidade de alinhamento na estrutura.sizeof(struct S4)Retorna a 64.
struct S4 {
int a;
// 28 bytes padding
struct S1 s1; // S4 inherits cache alignment requirement of S1
};
As três seguintes declarações de variáveis também usam __declspec(align(#)).Em cada caso, a variável deve ser alinhado 32 bytes.No caso do array, o endereço base da matriz, não a cada membro da matriz é 32 bytes alinhados.O sizeof valor de cada membro da matriz não é afetado pelo uso de __declspec(align(#)).
CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;
Para alinhar a cada membro individual de uma matriz, o código como o seguinte deve ser usado:
typedef CACHE_ALIGN struct { int a; } S5;
S5 array[10];
No exemplo a seguir, observe a alinhar a estrutura em si e alinhando o primeiro elemento são idênticas:
CACHE_ALIGN struct S6 {
int a;
int b;
};
struct S7 {
CACHE_ALIGN int a;
int b;
};
S6e S7 tem alinhamento idêntico, alocação e características de tamanho.
No exemplo a seguir, o alinhamento do inicial trata de a, b, c e d são 4, 1, 4 e 1, respectivamente.
void fn() {
int a;
char b;
long c;
char d[10]
}
O alinhamento se a memória foram alocada no heap depende de qual função de alocação é chamada.Por exemplo, se você usar malloc, o resultado depende do tamanho do operando.Se arg > = 8, alinhamento será alinhado em 8 bytes.If arg < 8, alinhamento será a primeira potência de 2 menor do que arg.Por exemplo, se você usar malloc(7), o alinhamento tem 4 bytes.
Definindo novos tipos de __declspec(align(#))
Você pode definir um tipo com uma característica de alinhamento.
Por exemplo, você pode definir um struct com um alinhamento do valor da seguinte maneira:
struct aType {int a; int b;};
typedef __declspec(align(32)) struct aType bType;
Agora, aType e bType são o mesmo tamanho (8 bytes), mas a variáveis do tipo bType serão alinhado 32 bytes.
Alinhamento de dados no armazenamento Local de segmento
Armazenamento local de segmento estático (TLS) criado com o __declspec(thread) de atributo e colocar na seção TLS no works a imagem para alinhamento exatamente como dados estáticos normais.O sistema operacional cria dados TLS alocando dados o tamanho da seção TLS e respeitando o atributo de alinhamento de seção TLS.
O exemplo a seguir mostra várias maneiras para inserir dados alinhados no armazenamento local de segmento.
// 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;
Como alinhar funciona com dados de remessa
O /Zp opção de compilador e o pack pragma têm o efeito de dados de remessa para membros de estrutura e união.Este exemplo mostra como /Zp e __declspec(align(#)) trabalham juntos:
struct S {
char a;
short b;
double c;
CACHE_ALIGN double d;
char e;
double f;
};
A tabela a seguir lista o deslocamento de cada membro em uma variedade de /Zp (ou # pragma pack) valores, mostrando como as duas interagem.
Variável |
/ Zp1 |
/ Zp2 |
/ Zp4 |
/ Zp8 |
---|---|---|---|---|
um |
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 |
Para obter mais informações, consulte /ZP (alinhamento de membro Struct).
Assim, o deslocamento de um objeto se baseia o deslocamento do objeto anterior e a configuração atual de embalagem, a menos que o objeto tem um __declspec(align(#)) de atributo, caso em que o alinhamento se baseia o deslocamento do objeto anterior e o __declspec(align(#)) valor para o objeto.