Udostępnij za pośrednictwem


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 identifierelementu , 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 pushprogramem przypisuje nazwę do rekordu w wewnętrznym stosie kompilatora. W przypadku użycia z popprogramem 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ą nwartoś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 /Zpkompilatora , która zapewnia tylko kontrolę na poziomie modułu. opakowanie ma zastosowanie w pierwszej structdeklaracji , unionlub 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 /Zpkompilatora . 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:

  • alignof

  • align

  • __unaligned

  • Przykłady wyrównania struktury x64

    Ostrzeżenie

    W programie Visual Studio 2015 lub nowszym można używać standardowych alignas i alignof 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ą packpragma 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

Zobacz też

Pragmadyrektywy i __pragma słowa kluczowe i _Pragma