pack pragma

指定结构、联合和类成员的封装对齐。

语法

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

参数

show
(可选)显示封装对齐的当前字节值。 该值由警告消息显示。

push
(可选)将当前封装对齐值推送到内部编译器堆栈上,并将当前封装对齐值设置为 n。 如果未指定 n,则将推送当前封装对齐值。

pop
(可选)从内部编译器堆栈的顶部移除记录。 如果没有用 pop 指定 n,则与堆栈顶部的生成的记录关联的封装值是新的封装对齐值。 如果指定了 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
(可选)指定要用于封装的值(以字节为单位)。 如果没有为模块设置编译器选项 /Zpn 的默认值为 8。 有效值为 1、2、4、8 和 16。 成员在作为 n 的倍数或成员的大小的倍数的边界(以较小者为准)上对齐。

注解

pack 类是将其成员直接逐一放在内存中。 这可能意味着,某些或全部成员可在小于目标体系结构的默认对齐的边界上对齐。 pack 提供了数据声明级别的控制。 它与编译器选项 /Zp 不同,该选项只提供模块级别控制。 在 pragma 出现之后,pack 在第一个 structunionclass 声明处生效。 pack 对定义没有影响。 在没有参数的情况下调用 pack 会将 n 设置为编译器选项 /Zp 中设置的值。 如果未设置编译器选项,则 x86、ARM 和 ARM64 的默认值为 8。 对于 x64 本机和 ARM64EC,默认值为 16。

如果更改结构的对齐方式,它可能不会占用太多内存空间。 但是,对于未对齐的访问,可能会看到性能丢失,甚至会引发硬件生成的异常。 可以使用 SetErrorMode 修改此异常行为。

有关如何修改对齐方式的详细信息,请参阅以下文章:

  • alignof

  • align

  • __unaligned

  • x64 结构对齐示例

    警告

    在 Visual Studio 2015 和更高版本中,可使用标准的 alignasalignof 运算符,这不同于 __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

以下示例演示如何使用 pushpopshow 语法。

// 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关键字