我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
Can I detect and change the current data alignment setting for structures in gcc/g++?
我的问题是基于此 wiki answer to the question of Why isn't sizeof for a struct equal to the sum of sizeof of each member? 的一部分(强调我的):
"IMPORTANT NOTE: Both the C and C++ standards state that structure alignment is implementation-defined. Therefore each compiler may choose to align data differently, resulting in different and incompatible data layouts. For this reason, when dealing with libraries that will be used by different compilers, it is important to understand how the compilers align data. Some compilers have command-line settings and/or special #pragma statements to change the structure alignment settings."
- 是否可以检测和更改 gcc/g++ 中的当前结构对齐设置?
- 如果是这样,我如何检测当前对齐设置+如何在 gcc/g++ 中更改它?
非常感谢您的帮助。
对于 C++,从 C++11 开始,您可以使用 alignas
and alignof
可移植地设置和获取任何类型的对齐方式。以下是 alignof
的 cppreference 示例,您可以在其中看到两者的实际效果:
#include <iostream>
struct Foo {
int i;
float f;
char c;
};
struct Empty {};
struct alignas(64) Empty64 {};
int main()
{
std::cout << "Alignment of" "\n"
"- char : " << alignof(char) << "\n"
"- pointer : " << alignof(int*) << "\n"
"- class Foo : " << alignof(Foo) << "\n"
"- empty class : " << alignof(Empty) << "\n"
"- alignas(64) Empty: " << alignof(Empty64) << "\n";
}
Possible output:
Alignment of
- char : 1
- pointer : 8
- class Foo : 4
- empty class : 1
- alignas(64) Empty: 64
应该注意 alignas
不允许您使用比对象默认需要的对齐方式更宽松的对齐方式。这意味着您不能使用它来 "pack",删除数据结构的填充。
Is it possible to ... change the current structure alignment setting in gcc/g++?
是的。 GCC 编译指示和命令行选项在 GCC 文档中有描述。
有一个命令行选项:
-fpack-struct[=n]
Without a value specified, pack all structure members together without holes. When a value is specified (which must be a small power of two), pack structure members according to this value, representing the maximum alignment (that is, objects with default alignment requirements larger than this are output potentially unaligned at the next fitting location.
Warning: the -fpack-struct switch causes GCC to generate code that is not binary compatible with code generated without that switch. Additionally, it makes the code suboptimal. Use it to conform to a non-default application binary interface.
和编译指示:
For compatibility with Microsoft Windows compilers, GCC supports a set
of #pragma directives which change the maximum alignment of members of
structures (other than zero-width bitfields), unions, and classes
subsequently defined. The n value below always is required to be a
small power of two and specifies the new alignment in bytes.
#pragma pack(n)
simply sets the new alignment.
#pragma pack()
sets the alignment to the one that was in effect when compilation started (see also command line option
-fpack-struct[=] see Code Gen Options).
#pragma pack(push[,n])
pushes the current alignment setting on an internal stack and then optionally sets the new alignment.
#pragma pack(pop)
restores the alignment setting to the one saved at the top of the internal stack (and removes that stack entry). Note
that #pragma pack([n])
does not influence this internal stack; thus it
is possible to have #pragma pack(push)
followed by multiple #pragma pack(n)
instances and finalized by a single #pragma pack(pop)
.
Some targets, e.g. i386 and powerpc, support the ms_struct #pragma
which lays out a structure as the documented __attribute__ ((ms_struct))
.
#pragma ms_struct on
turns on the layout for structures declared.
#pragma ms_struct off
turns off the layout for structures declared.
#pragma ms_struct reset
goes back to the default layout.
Is it possible to detect ... the current structure alignment setting in gcc/g++?
很大程度上取决于您所说的 "detect" 是什么意思。有以下命令行选项:
-frecord-gcc-switches
This switch causes the command line that was used to invoke the
compiler to be recorded into the object file that is being created.
This switch is only implemented on some targets and the exact
format of the recording is target and binary file format dependent,
but it usually takes the form of a section containing ASCII text.
如果使用了这样的选项,那么您可以通过检查二进制文件来检测是否使用了-fpack-struct[=n]。
如果您只想知道特定类型的对齐方式,可以使用 alignof
运算符。如果你想知道任何标量类型的最大对齐,你可以使用 alignof(std::max_align_t)
。您可以指定 classes 或数组比 alignas
具有更严格的对齐方式。如果它超过 std::max_align_t
的对齐方式,那么 class 被称为过度对齐。
我的问题是基于此 wiki answer to the question of Why isn't sizeof for a struct equal to the sum of sizeof of each member? 的一部分(强调我的):
"IMPORTANT NOTE: Both the C and C++ standards state that structure alignment is implementation-defined. Therefore each compiler may choose to align data differently, resulting in different and incompatible data layouts. For this reason, when dealing with libraries that will be used by different compilers, it is important to understand how the compilers align data. Some compilers have command-line settings and/or special #pragma statements to change the structure alignment settings."
- 是否可以检测和更改 gcc/g++ 中的当前结构对齐设置?
- 如果是这样,我如何检测当前对齐设置+如何在 gcc/g++ 中更改它?
非常感谢您的帮助。
对于 C++,从 C++11 开始,您可以使用 alignas
and alignof
可移植地设置和获取任何类型的对齐方式。以下是 alignof
的 cppreference 示例,您可以在其中看到两者的实际效果:
#include <iostream> struct Foo { int i; float f; char c; }; struct Empty {}; struct alignas(64) Empty64 {}; int main() { std::cout << "Alignment of" "\n" "- char : " << alignof(char) << "\n" "- pointer : " << alignof(int*) << "\n" "- class Foo : " << alignof(Foo) << "\n" "- empty class : " << alignof(Empty) << "\n" "- alignas(64) Empty: " << alignof(Empty64) << "\n"; }
Possible output:
Alignment of - char : 1 - pointer : 8 - class Foo : 4 - empty class : 1 - alignas(64) Empty: 64
应该注意 alignas
不允许您使用比对象默认需要的对齐方式更宽松的对齐方式。这意味着您不能使用它来 "pack",删除数据结构的填充。
Is it possible to ... change the current structure alignment setting in gcc/g++?
是的。 GCC 编译指示和命令行选项在 GCC 文档中有描述。
有一个命令行选项:
-fpack-struct[=n]
Without a value specified, pack all structure members together without holes. When a value is specified (which must be a small power of two), pack structure members according to this value, representing the maximum alignment (that is, objects with default alignment requirements larger than this are output potentially unaligned at the next fitting location.
Warning: the -fpack-struct switch causes GCC to generate code that is not binary compatible with code generated without that switch. Additionally, it makes the code suboptimal. Use it to conform to a non-default application binary interface.
和编译指示:
For compatibility with Microsoft Windows compilers, GCC supports a set of #pragma directives which change the maximum alignment of members of structures (other than zero-width bitfields), unions, and classes subsequently defined. The n value below always is required to be a small power of two and specifies the new alignment in bytes.
#pragma pack(n)
simply sets the new alignment.#pragma pack()
sets the alignment to the one that was in effect when compilation started (see also command line option -fpack-struct[=] see Code Gen Options).#pragma pack(push[,n])
pushes the current alignment setting on an internal stack and then optionally sets the new alignment.#pragma pack(pop)
restores the alignment setting to the one saved at the top of the internal stack (and removes that stack entry). Note that #pragma pack([n])
does not influence this internal stack; thus it is possible to have#pragma pack(push)
followed by multiple#pragma pack(n)
instances and finalized by a single#pragma pack(pop)
.Some targets, e.g. i386 and powerpc, support the ms_struct #pragma which lays out a structure as the documented
__attribute__ ((ms_struct))
.
#pragma ms_struct on
turns on the layout for structures declared.#pragma ms_struct off
turns off the layout for structures declared.#pragma ms_struct reset
goes back to the default layout.
Is it possible to detect ... the current structure alignment setting in gcc/g++?
很大程度上取决于您所说的 "detect" 是什么意思。有以下命令行选项:
-frecord-gcc-switches
This switch causes the command line that was used to invoke the compiler to be recorded into the object file that is being created. This switch is only implemented on some targets and the exact format of the recording is target and binary file format dependent, but it usually takes the form of a section containing ASCII text.
如果使用了这样的选项,那么您可以通过检查二进制文件来检测是否使用了-fpack-struct[=n]。
如果您只想知道特定类型的对齐方式,可以使用 alignof
运算符。如果你想知道任何标量类型的最大对齐,你可以使用 alignof(std::max_align_t)
。您可以指定 classes 或数组比 alignas
具有更严格的对齐方式。如果它超过 std::max_align_t
的对齐方式,那么 class 被称为过度对齐。