首页 > 解决方案 > 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?

问题描述

我的问题是基于this wiki answer的一部分,为什么结构的sizeof不等于每个成员的sizeof之和?(强调我的):

“重要提示:C 和 C++ 标准都声明结构对齐是实现定义的。因此,每个编译器可能会选择以不同方式对齐数据,从而导致不同且不兼容的数据布局。因此,在处理将由“ _ _

非常感谢您的帮助。

标签: c++cgccg++memory-alignment

解决方案


是否可以...更改 gcc/g++ 中的当前结构对齐设置?

是的。GCC 编译指示和命令行选项在 GCC 文档中进行了描述。

有一个命令行选项:

-fpack-struct[=n]

如果没有指定值,则将所有结构成员打包在一起,不带孔。当指定一个值(必须是 2 的小幂)时,根据该值打包结构成员,表示最大对齐(即默认对齐要求大于此值的对象在下一个拟合位置输出可能未对齐。

警告:-fpack-struct 开关会导致 GCC 生成与没有该开关生成的代码二进制不兼容的代码。此外,它使代码次优。使用它来符合非默认应用程序二进制接口。

和语用:

为了与 Microsoft Windows 编译器兼容,GCC 支持一组 #pragma 指令,这些指令更改随后定义的结构(零宽度位域除外)、联合和类的成员的最大对齐方式。下面的 n 值总是要求是 2 的小幂,并以字节为单位指定新的对齐方式。

  1. #pragma pack(n)只需设置新的对齐方式。
  2. #pragma pack()将对齐设置为编译开始时生效的对齐(另请参见命令行选项 -fpack-struct[=] 参见代码生成选项)。
  3. #pragma pack(push[,n])将当前对齐设置推送到内部堆栈,然后可选地设置新对齐方式。
  4. #pragma pack(pop)将对齐设置恢复为保存在内部堆栈顶部的对齐设置(并删除该堆栈条目)。请注意,#pragma pack([n])不会影响此内部堆栈;因此,有可能#pragma pack(push)跟随多个#pragma pack(n)实例并由单个#pragma pack(pop).

一些目标,例如 i386 和 powerpc,支持 ms_struct #pragma,它将结构布局为文档中的__attribute__ ((ms_struct)).

  1. #pragma ms_struct on打开声明的结构的布局。
  2. #pragma ms_struct off关闭声明结构的布局。
  3. #pragma ms_struct reset回到默认布局。

是否可以检测到... gcc/g++ 中的当前结构对齐设置?

很大程度上取决于“检测”的含义。有以下命令行选项:

-frecord-gcc-switches

此开关导致用于调用编译器的命令行被记录到正在创建的目标文件中。此开关仅在某些目标上实现,并且录制的确切格式取决于目标和二进制文件格式,但它通常采用包含 ASCII 文本的部分的形式。

如果使用了这样的选项,那么您可以通过检查二进制文件来检测是否使用了 -fpack-struct[=n]。


如果您只是想知道特定类型的对齐方式,可以使用alignof运算符。如果您想知道任何标量类型的最大对齐方式,您可以使用alignof(std::max_align_t). 您可以指定类或数组,使其具有比在其他情况下更严格的对齐方式alignas。如果超过 的对齐std::max_align_t,则称该类过度对齐。


推荐阅读