pack
pragma
Especifica la alineación de empaquetado de los miembros de estructura, unión y clase.
Sintaxis
#pragma pack( show )
#pragma pack( push
[,
identifier
] [,
n
])
#pragma pack( pop
[,
{identifier
|n
} ])
#pragma pack(
[n
])
Parámetros
show
(Opcional) Muestra el valor de byte actual de la alineación de empaquetado. El valor se muestra mediante un mensaje de advertencia.
push
(Opcional) Inserta el valor de alineación de empaquetado actual en la pila interna del compilador y establece el valor actual de alineación de empaquetado en n. Si no se especifica n, se inserta el valor actual de alineación de empaquetado.
pop
(Opcional) Quita el registro de la parte superior de la pila interna del compilador. Si no se especifica n con pop
, el valor de empaquetado asociado al registro resultante en la parte superior de la pila es el nuevo valor de alineación de empaquetado. Si se especifica n, por ejemplo, #pragma pack(pop, 16)
, n se convierte en el nuevo valor de alineación de empaquetado. Si saca con un identifier
, por ejemplo, #pragma pack(pop, r1)
, se sacan todos los registros de la pila hasta encontrar el que tiene identifier
. Ese registro se saca y el valor de empaquetado asociado al registro encontrado en la parte superior de la pila es el nuevo valor de alineación de empaquetado. Si saca con un identifier
que no se encuentra en ningún registro de la pila, pop
se omite.
La instrucción #pragma pack (pop, r1, 2)
es equivalente a #pragma pack (pop, r1)
seguida de #pragma pack(2)
.
identifier
(Opcional) Cuando se usa con push
, asigna un nombre al registro en la pila interna del compilador. Cuando se usa con pop
, saca los registros de la pila interna hasta que se quita identifier
. Si no se encuentra identifier
en la pila interna, no se saca nada.
n
(Opcional) Especifica el valor, en bytes, que se va a usar para el empaquetado. Si no se establece la opción del compilador /Zp
para el módulo, el valor predeterminado de n
es 8. Los valores válidos son 1, 2, 4, 8 y 16. La alineación de un miembro está en un límite que es múltiplo de n
o múltiplo del tamaño del miembro, el que sea menor.
Comentarios
Empaquetar una clase es colocar sus miembros uno detrás de otro en la memoria. Puede significar que algunos o todos los miembros se alineen según un límite menor que la alineación predeterminada de la arquitectura de destino. pack
proporciona control en el nivel de declaración de datos. Esto difiere de la opción del compilador /Zp
, que solo proporciona control en el nivel de módulo. pack se aplica en la primera declaración struct
, union
o class
tras la detección de pragma. pack
no tiene ningún efecto en las definiciones. Una llamada a pack
sin argumentos establece n
en el valor establecido en la opción del compilador /Zp
. Si no se establece la opción del compilador, el valor predeterminado es 8 en x86, ARM y ARM64. El valor predeterminado es 16 en x64 nativo y ARM64EC.
Si cambia la alineación de una estructura, puede que no se use tanto espacio en memoria. Pero es posible que note una pérdida de rendimiento o incluso que reciba una excepción generada por el hardware de acceso no alineado. Puede modificar este comportamiento de excepción mediante SetErrorMode
.
Para obtener más información sobre cómo modificar la alineación, vea estos artículos:
Ejemplos de alineación de estructuras x64
Advertencia
En Visual Studio 2015 y posterior puede usar los operadores estándar
alignas
yalignof
, que, a diferencia de__alignof
y__declspec( align )
, son portátiles entre compiladores. El estándar C++ no se ocupa del empaquetado, por lo que debe seguir usandopack
(o la extensión que corresponda en otros compiladores) para especificar alineaciones que sean inferiores al tamaño de palabra de la arquitectura de destino.
Ejemplos
En el ejemplo siguiente se muestra cómo usar pack
pragma para cambiar la alineación de una estructura.
// 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
En el siguiente ejemplo se muestra cómo usar la sintaxis push, pop y show.
// 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