packpragma

Задает выравнивание упаковки для членов структуры, объединения и класса.

Синтаксис

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

Параметры

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

push
Используемых Помещает текущее значение выравнивания упаковки во внутренний стек компилятора и устанавливает для текущего значения выравнивания упаковки значение n. Если n не задано, текущее значение выравнивания упаковки помещается.

pop
Используемых Удаляет запись из верхнего внутреннего стека компилятора. Если n не указано в , то значение упаковки, связанное с результирующей записью в верхней части стека, — это новое значение выравнивания упаковки. Если указано значение n , то, например , n становится новым значением выравнивания упаковки. Если вы identifier открыли с помощью, например, #pragma pack(pop, r1) то все записи в стеке будут извлечены до тех пор, пока не будет identifier найдена запись. Эта запись извлекается, а значение упаковки, связанное с записью, найденной в верхней части стека, становится новым значением выравнивания упаковки. Если POP используется 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 , который обеспечивает только управление на уровне модуля. пакет вступает в силу в первом union объявлении, или после того, class как pragma будет показан. packДиректива не действует на определения. Вызов pack без аргументов задает n значение, заданное в параметре компилятора /Zp . Если параметр компилятора не установлен, по умолчанию используется значение 8 для x86, ARM и ARM64. Значение по умолчанию — 16 для машинного кода 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-и-- keyword- pragma ключевое слово "Data-ссылок =" относительного пути ">директивы pragma и __pragma_Pragma Ключевые слова и