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
или union
class
объявлении pragma после того, как он будет замечен. pack
не влияет на определения. Вызов pack
без аргументов, заданных n
в параметре /Zp
компилятора. Если параметр компилятора не задан, значение по умолчанию — 8 для x86, ARM и ARM64. Значение по умолчанию — 16 для машинного и ARM64EC x64.
При изменении выравнивания структуры он может не использовать столько места в памяти. Однако может возникнуть потеря производительности или даже получить исключение, созданное оборудованием, для неуправляемого доступа. Это поведение исключения можно изменить с помощью SetErrorMode
.
Дополнительные сведения об изменении выравнивания см. в следующих статьях:
Примеры выравнивания структуры x64
Предупреждение
В Visual Studio 2015 и более поздних версиях можно использовать стандартные
alignas
иalignof
операторы, в отличие от__alignof
__declspec( align )
них и переносимых между компиляторами. Стандарт C++ не использует упаковку, поэтому необходимо использоватьpack
(или соответствующее расширение для других компиляторов), чтобы указать выравнивания меньше размера слова целевой архитектуры.
Примеры
В следующем примере показано, как изменить pack
pragma выравнивание структуры.
// 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