pack
pragma
Określa wyrównanie pakowania dla składowych struktury, unii i klasy.
Składnia
#pragma pack( show )
#pragma pack( push
[ ] [,
,
identifier
n
])
#pragma pack( pop
[ {,
identifier
|n
} ])
#pragma pack(
[n
])
Parametry
show
(Opcjonalnie) Wyświetla bieżącą wartość bajtu dla wyrównania pakowania. Wartość jest wyświetlana przez komunikat ostrzegawczy.
push
(Opcjonalnie) Wypycha bieżącą wartość wyrównania pakowania na wewnętrznym stosie kompilatora i ustawia bieżącą wartość wyrównania pakowania na n. Jeśli n nie zostanie określony, bieżąca wartość wyrównania pakowania zostanie wypchnięta.
pop
(Opcjonalnie) Usuwa rekord z góry wewnętrznego stosu kompilatora. Jeśli n nie zostanie określony z wartością pop
, wartość pakowania skojarzona z wynikowym rekordem w górnej części stosu to nowa wartość wyrównania pakowania. Jeśli n jest określony, na przykład , #pragma pack(pop, 16)
n staje się nową wartością wyrównania pakowania. Jeśli zostanie wyświetlone okno podręczne przy użyciu identifier
elementu , na przykład #pragma pack(pop, r1)
, wszystkie rekordy na stosie zostaną wyświetlone do momentu znalezienia rekordu identifier
. Ten rekord jest zwinięty, a wartość pakowania skojarzona z rekordem znalezionym w górnej części stosu staje się nową wartością wyrównania pakowania. Jeśli używasz elementu identifier
, który nie znajduje się w żadnym rekordzie na stosie, pop
zostanie on zignorowany.
#pragma pack (pop, r1, 2)
Instrukcja jest równoważna instrukcji #pragma pack (pop, r1)
, po której #pragma pack(2)
następuje .
identifier
(Opcjonalnie) W przypadku użycia z push
programem przypisuje nazwę do rekordu w wewnętrznym stosie kompilatora. W przypadku użycia z pop
programem polecenie wyskakuje rekordy poza stos wewnętrzny do czasu identifier
usunięcia. Jeśli identifier
nie zostanie znaleziony na stosie wewnętrznym, nic nie zostanie pominięte.
n
(Opcjonalnie) Określa wartość w bajtach, która ma być używana do pakowania. Jeśli opcja /Zp
kompilatora nie jest ustawiona dla modułu, wartość domyślna to n
8. Prawidłowe wartości to 1, 2, 4, 8 i 16. Wyrównanie elementu członkowskiego znajduje się na granicy, która jest wielokrotną n
wartością lub wielokrotną wielkości elementu członkowskiego, w zależności od tego, która z nich jest mniejsza.
Uwagi
Aby spakować klasę, należy umieścić jej składowe bezpośrednio po sobie w pamięci. Może to oznaczać, że niektóre lub wszystkie elementy członkowskie mogą być wyrównane do granicy mniejszej niż domyślne wyrównanie architektury docelowej. pack
zapewnia kontrolę na poziomie deklaracji danych. Różni się on od opcji /Zp
kompilatora , która zapewnia tylko kontrolę na poziomie modułu. opakowanie ma zastosowanie w pierwszej struct
deklaracji , union
lub class
po wystąpieniu pragma . pack
nie ma wpływu na definicje. Wywołanie pack
bez argumentów powoduje ustawienie n
wartości ustawionej w opcji /Zp
kompilatora . Jeśli opcja kompilatora nie jest ustawiona, wartość domyślna to 8 dla x86, ARM i ARM64. Wartość domyślna to 16 dla architektury natywnej x64 i ARM64EC.
Jeśli zmienisz wyrównanie struktury, może nie używać tyle miejsca w pamięci. Jednak może wystąpić utrata wydajności, a nawet uzyskanie wyjątku wygenerowanego przez sprzęt w przypadku nieprzygotowanego dostępu. To zachowanie wyjątku można zmodyfikować przy użyciu polecenia SetErrorMode
.
Aby uzyskać więcej informacji na temat modyfikowania wyrównania, zobacz następujące artykuły:
Przykłady wyrównania struktury x64
Ostrzeżenie
W programie Visual Studio 2015 lub nowszym można używać standardowych
alignas
ialignof
operatorów, które w przeciwieństwie do__alignof
__declspec( align )
i są przenośne w kompilatorach. Standard C++ nie obsługuje pakowania, dlatego należy nadal używaćpack
(lub odpowiedniego rozszerzenia w innych kompilatorach), aby określić wyrównania mniejsze niż rozmiar słowa architektury docelowej.
Przykłady
W poniższym przykładzie pokazano, jak zmienić wyrównanie struktury za pomocą pack
pragma obiektu .
// 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
W poniższym przykładzie pokazano, jak używać wypychania, wyskakującego okienka i pokazywania składni.
// 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