pack
pragma
Especifica o alinhamento de empacotamento da estrutura, união e membros da 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 atual de byte para o alinhamento de empacotamento. O valor é exibido por uma mensagem de aviso.
push
(Opcional) Impulsiona o valor atual do alinhamento de empacotamento na pilha interna do compilador e define o valor atual do alinhamento do empacotamento atual como n. Se n não for especificado, o valor atual do alinhamento do empacotamento é impulsionado.
pop
(Opcional) Remove o registro da parte superior da pilha interna do compilador. Se n não for especificado com pop
, o valor de empacotamento associado ao registro resultante na parte superior da pilha é o novo valor do alinhamento de empacotamento. Se n for especificado, por exemplo, #pragma pack(pop, 16)
, nse torna o novo valor de alinhamento de empacotamento. Se você remover mais recente da pilha com identifier
, por exemplo, #pragma pack(pop, r1)
, todos os registros na pilha são removidos até que o registro que tem identifier
seja localizado. Esse registro é removido e o valor de empacotamento associado ao registro resultante na parte superior da pilha é o novo valor do alinhamento de empacotamento. Se você remover com identifier
que não foi encontrado em nenhum registro na pilha, então pop
é ignorado.
A instrução #pragma pack (pop, r1, 2)
é equivalente a #pragma pack (pop, r1)
seguida por #pragma pack(2)
.
identifier
(Opcional) Quando usado com push
, atribui um nome ao registro na pilha interna do compilador. Quando usado com pop
, remove 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
é 8. Os valores válidos são 1, 2, 4, 8 e 16. O alinhamento de um membro estará em um limite que é múltiplo de n
ou múltiplo do tamanho do membro, o que for menor.
Comentários
Para empacotar uma classe deve-se 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 que o alinhamento padrão da arquitetura de destino. pack
oferece controle a nível de declaração de dados. Isso é diferente da opção de compilador /Zp
, que fornece apenas o controle a nível de módulo. pacote entra em vigor na primeira declaração struct
, union
ou class
após pragma ser visualizado. pack
não tem nenhum efeito nas definições. Chamar pack
sem argumentos define n
como um valor definido na opção de compilador /Zp
. Se a opção do compilador não for 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, pode não usar muito 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 atribuído. Você pode alterar 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
Aviso
No Visual Studio 2015 e posterior, você pode usar o padrão de operadores
alignas
ealignof
, que ao contrário__alignof
e__declspec( align )
são portáteis entre compiladores. O padrão C++ não aborda o empacotamento, portanto, você ainda deve usarpack
(ou a extensão correspondente em outros compiladores) para especificar alinhamentos menores 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, pop e 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