pack
pragma
Especifica o alinhamento de empacotamento para membros da estrutura, união e classe.
Sintaxe
#pragma pack( show )
#pragma pack( push
[,
identifier
] [,
n
])
#pragma pack( pop
[,
{identifier
|n
} ])
#pragma pack(
[n
])
Parâmetros
show
(Opcional) Exibe o valor de byte atual para alinhamento de embalagem. O valor é exibido por uma mensagem de aviso.
push
(Opcional) Empurra o valor de alinhamento de empacotamento atual na pilha interna do compilador e define o valor de alinhamento de empacotamento atual como n. Se n não for especificado, o valor atual do alinhamento da embalagem será enviado.
pop
(Opcional) Remove o registro da parte superior da pilha interna do compilador. Se n não for especificado com pop
, o valor de embalagem associado ao registro resultante na parte superior da pilha será o novo valor de alinhamento de embalagem. Se n for especificado, por exemplo, #pragma pack(pop, 16)
, n se tornará o novo valor de alinhamento da embalagem. Se você aparecer usando um identifier
, por exemplo, #pragma pack(pop, r1)
, todos os registros na pilha serão exibidos até que o registro que identifier
seja encontrado. Esse registro é exibido e o valor de empacotamento associado ao registro encontrado na parte superior da pilha torna-se o novo valor de alinhamento de embalagem. Se você aparecer usando um identifier
que não é encontrado em nenhum registro na pilha, o pop
será ignorado.
A declaração #pragma pack (pop, r1, 2)
é equivalente a #pragma pack (pop, r1)
seguida de #pragma pack(2)
.
identifier
(Opcional) Quando usado com push
, atribui um nome ao registro na pilha interna do compilador. Quando usado com pop
, retira registros da pilha interna até que identifier
seja removido. Se identifier
não for encontrado na pilha interna, nada será exibido.
n
(Opcional) Especifica o valor, em bytes, a ser usado para empacotamento. Se a opção do compilador /Zp
não estiver definida para o módulo, o valor padrão para n
será 8. Os valores válidos são 1, 2, 4, 8 e 16. O alinhamento de um membro está em um limite que é um múltiplo de n
ou um múltiplo do tamanho do membro, o que for menor.
Comentários
Para pacote uma classe é colocar seus membros diretamente um após o outro na memória. Isso pode significar que alguns ou todos os membros podem ser alinhados em um limite menor do que o alinhamento padrão da arquitetura de destino.
pack
dá controle no nível da declaração de dados. Ele difere da opção do compilador /Zp
, que fornece apenas controle no nível do módulo.
embalagem entra em vigor no primeiro struct
, union
ou class
declaração após a pragma ser vista.
pack
não tem qualquer efeito sobre as definições. Chamar pack
sem argumentos define n
para o valor definido na opção do compilador /Zp
. Se a opção do compilador não estiver definida, o valor padrão será 8 para x86, ARM e ARM64. O padrão é 16 para x64 nativo e ARM64EC.
Se você alterar o alinhamento de uma estrutura, ela pode não usar tanto espaço na memória. No entanto, você pode ver uma perda de desempenho ou até mesmo obter uma exceção gerada por hardware para acesso não alinhado. Você pode modificar esse comportamento de exceção usando SetErrorMode
.
Para obter mais informações sobre como modificar o alinhamento, consulte estes artigos:
exemplos de alinhamento de estrutura x64
Advertência
No Visual Studio 2015 e posterior, você pode usar os operadores
alignas
ealignof
padrão, que, ao contrário__alignof
e__declspec( align )
, são portáteis entre compiladores. O padrão C++ não aborda o empacotamento, então você ainda deve usarpack
(ou a extensão correspondente em outros compiladores) para especificar alinhamentos menores do que o tamanho da palavra da arquitetura de destino.
Exemplos
O exemplo a seguir mostra como usar o pack
pragma para alterar o alinhamento de uma estrutura.
// pragma_directives_pack.cpp
#include <stddef.h>
#include <stdio.h>
struct S {
int i; // size 4
short j; // size 2
double k; // size 8
};
#pragma pack(2)
struct T {
int i;
short j;
double k;
};
int main() {
printf("%zu ", offsetof(S, i));
printf("%zu ", offsetof(S, j));
printf("%zu\n", offsetof(S, k));
printf("%zu ", offsetof(T, i));
printf("%zu ", offsetof(T, j));
printf("%zu\n", offsetof(T, k));
}
0 4 8
0 4 6
O exemplo a seguir mostra como usar o push, pope mostrar sintaxe.
// pragma_directives_pack_2.cpp
// compile with: /W1 /c
#pragma pack() // n defaults to 8; equivalent to /Zp8
#pragma pack(show) // C4810
#pragma pack(4) // n = 4
#pragma pack(show) // C4810
#pragma pack(push, r1, 16) // n = 16, pushed to stack
#pragma pack(show) // C4810
// pop to the identifier and then set
// the value of the current packing alignment:
#pragma pack(pop, r1, 2) // n = 2 , stack popped
#pragma pack(show) // C4810