Поделиться через


pack pragma

Указывает выравнивание упаковки для элементов структуры, объединения и класса.

Синтаксис

#pragma pack( show )
#pragma pack( push[ , identifier ] [ ] , n)
#pragma pack( pop [ , { identifier | n } ] )
#pragma pack([ ] n)

Параметры

show
(Необязательно) Отображает текущее значение байта для выравнивания упаковки. Значение отображается в предупреждении.

push
(Необязательно) Отправляет текущее значение выравнивания упаковки во внутренний стек компилятора и задает текущее значение выравнивания упаковки на n. Если значение выравнивания упаковки не указано, отправляется текущее значение выравнивания упаковки.

pop
(Необязательно) Удаляет запись из верхней части внутреннего стека компилятора. Если значение n не указано pop, то значение упаковки, связанное с результирующей записью в верхней части стека, является новым значением выравнивания упаковки. Если задано значение n, например#pragma pack(pop, 16), n становится новым значением выравнивания упаковки. Если вы появляетсяе с помощью identifier, например, все записи в стеке будут всплывают до тех пор, #pragma pack(pop, r1)пока не будет найдена запись identifier . Эта запись возвращается, а значение упаковки, связанное с записью, найденной в верхней части стека, становится новым значением выравнивания упаковки. Если вы используете не найденную identifier запись в стеке, pop то она игнорируется.

#pragma pack (pop, r1, 2) Оператор эквивалентен следующему #pragma pack (pop, r1) #pragma pack(2).

identifier
(Необязательно) При использовании с pushименем назначается запись во внутреннем стеке компилятора. При использовании с pop, всплывает записи из внутреннего стека, пока не identifier будет удалено. Если identifier он не найден во внутреннем стеке, ничего не отображается.

n
(Необязательно) Указывает значение в байтах, которое будет использоваться для упаковки. Если параметр /Zp компилятора не задан для модуля, значение n по умолчанию равно 8. Допустимые значения: 1, 2, 4, 8 и 16. Выравнивание элемента находится на границе, которая является либо несколькими n, либо несколькими размерами элемента, в зависимости от того, что меньше.

Замечания

Чтобы упаковать класс, следует поместить его члены непосредственно друг за другом в память. Это может означать, что некоторые или все элементы можно выровнять по границе меньше, чем выравнивание по умолчанию целевой архитектуры. pack обеспечивает контроль на уровне объявления данных. Он отличается от параметра /Zpкомпилятора, который предоставляет только элемент управления на уровне модуля. пакет вступает в силу в первом structили unionclass объявлении pragma после того, как он будет замечен. pack не влияет на определения. Вызов pack без аргументов, заданных n в параметре /Zpкомпилятора. Если параметр компилятора не задан, значение по умолчанию — 8 для x86, ARM и ARM64. Значение по умолчанию — 16 для машинного и ARM64EC x64.

При изменении выравнивания структуры он может не использовать столько места в памяти. Однако может возникнуть потеря производительности или даже получить исключение, созданное оборудованием, для неуправляемого доступа. Это поведение исключения можно изменить с помощью SetErrorMode.

Дополнительные сведения об изменении выравнивания см. в следующих статьях:

  • alignof

  • align

  • __unaligned

  • Примеры выравнивания структуры x64

    Предупреждение

    В Visual Studio 2015 и более поздних версиях можно использовать стандартные alignas и alignof операторы, в отличие от __alignof __declspec( align ) них и переносимых между компиляторами. Стандарт C++ не использует упаковку, поэтому необходимо использовать pack (или соответствующее расширение для других компиляторов), чтобы указать выравнивания меньше размера слова целевой архитектуры.

Примеры

В следующем примере показано, как изменить packpragma выравнивание структуры.

// 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

В следующем примере показано, как использовать синтаксис push, pop и отображения синтаксиса.

// 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

См. также

Pragma директивы и ключевые __pragma _Pragma слова