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:

  • alignof

  • align

  • __unaligned

  • Exemplos de alinhamento de estrutura x64

    Aviso

    No Visual Studio 2015 e posterior, você pode usar o padrão de operadores alignas e alignof, 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 usar pack (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 packpragma 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

Confira também

Pragmadiretivas e as __pragma palavras-chave e _Pragma