pack
pragma
Určuje zarovnání balení pro členy struktury, sjednocení a třídy.
Syntaxe
#pragma pack( show )
#pragma pack( push
[] [,
,
identifier
n
])
#pragma pack( pop
[,
{identifier
|n
} ])
#pragma pack(
[ ]n
)
Parametry
show
(Volitelné) Zobrazí aktuální hodnotu bajtu pro zarovnání balení. Tato hodnota se zobrazí zprávou s upozorněním.
push
(Volitelné) Nasdílí aktuální hodnotu zarovnání balení do zásobníku interního kompilátoru a nastaví aktuální hodnotu zarovnání balení na n. Pokud není zadána hodnota n , aktuální hodnota zarovnání balení se nasdílí.
pop
(Volitelné) Odebere záznam z horní části interního zásobníku kompilátoru. Pokud n není zadán pop
s , pak hodnota balení přidružená k výslednému záznamu v horní části zásobníku je nová hodnota zarovnání balení. Pokud je například zadán #pragma pack(pop, 16)
n , n se stane novou hodnotou zarovnání balení. Pokud například spustíte okno s použitím záznamu identifier
, zobrazí se všechny záznamy v zásobníku, #pragma pack(pop, r1)
dokud se nenajde záznam.identifier
Tento záznam se přepne a hodnota balení přidružená k záznamu nalezeného v horní části zásobníku se stane novou hodnotou zarovnání balení. Pokud se zobrazí okno identifier
s použitím záznamu, který není v žádném záznamu v zásobníku, bude pop
ignorován.
#pragma pack (pop, r1, 2)
Příkaz je ekvivalentní #pragma pack (pop, r1)
následovaný #pragma pack(2)
.
identifier
(Volitelné) Při použití se push
záznamem v interním zásobníku kompilátoru přiřadí název záznamu. Při použití se pop
vyskočí záznamy z interního zásobníku, dokud identifier
se neodebere. Pokud identifier
se na interním zásobníku nenajde, nic se nevypíná.
n
(Volitelné) Určuje hodnotu v bajtech, která se má použít pro balení. Pokud není pro modul nastavená možnost /Zp
kompilátoru, je výchozí hodnota n
8. Platné hodnoty jsou 1, 2, 4, 8 a 16. Zarovnání člena je na hranici, která je buď násobkem n
, nebo násobkem velikosti členu, podle toho, co je menší.
Poznámky
Zabalení třídy spočívá v umístění členů přímo za sebou do paměti. Může to znamenat, že některé nebo všechny členy mohou být zarovnány na hranici menší než výchozí zarovnání cílové architektury. pack
poskytuje kontrolu na úrovni deklarace dat. Liší se od možnosti /Zp
kompilátoru, která poskytuje pouze řízení na úrovni modulu. balení se projeví na prvním struct
místě , union
nebo class
prohlášení po jeho výskytu pragma . pack
nemá žádný vliv na definice. Volání pack
bez argumentů se nenastavuje n
na hodnotu nastavenou v možnosti /Zp
kompilátoru . Pokud není možnost kompilátoru nastavená, výchozí hodnota je 8 pro x86, ARM a ARM64. Výchozí hodnota je 16 pro nativní platformu x64 a ARM64EC.
Pokud změníte zarovnání struktury, nemusí se v paměti používat tolik místa. Můžete však zaznamenat ztrátu výkonu nebo dokonce získat výjimku vygenerovanou hardwarem pro nerovnaný přístup. Toto chování výjimky můžete upravit pomocí .SetErrorMode
Další informace o úpravě zarovnání najdete v těchto článcích:
Příklady zarovnání struktury x64
Upozorňující
V sadě Visual Studio 2015 a novějších můžete použít standardní
alignas
aalignof
operátory, na rozdíl od__declspec( align )
__alignof
a jsou přenositelné mezi kompilátory. Standard C++ nezabývá balením, takže je nutné použítpack
(nebo odpovídající rozšíření u jiných kompilátorů) k určení zarovnání menší než velikost slova cílové architektury.
Příklady
Následující ukázka ukazuje, jak použít pack
pragma ke změně zarovnání struktury.
// 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
Následující ukázka ukazuje, jak používat syntaxi push, pop a 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