编译器对结构进行重新排序 [英] Struct Reordering by compiler
问题描述
假设我有一个这样的结构:
struct MyStruct
{
uint8_t var0;
uint32_t var1;
uint8_t var2;
uint8_t var3;
uint8_t var4;
};
这可能会浪费一堆(不是一吨)的空间.这是因为uint32_t
变量必须进行对齐.
实际上(在对齐结构以便可以实际使用uint32_t
变量之后),它看起来可能像这样:
struct MyStruct
{
uint8_t var0;
uint8_t unused[3]; //3 bytes of wasted space
uint32_t var1;
uint8_t var2;
uint8_t var3;
uint8_t var4;
};
更有效的结构是:
struct MyStruct
{
uint8_t var0;
uint8_t var2;
uint8_t var3;
uint8_t var4;
uint32_t var1;
};
现在,问题是:
为什么(标准)禁止编译器对结构进行重新排序?
如果结构重新排序,我看不出有什么办法可以让自己在脚上开枪.
为什么(按标准)禁止编译器对结构进行重新排序?
基本原因是:与C兼容.
请记住,C最初是一种高级汇编语言.在C语言中,通过将字节重新解释为特定的struct
来查看内存(网络数据包等)是很常见的.
这导致了依赖此属性的多个功能:
-
C保证
struct
的地址和它的第一个数据成员的地址是相同的,因此C ++也是如此(在没有virtual
继承/方法的情况下). -
C保证如果您有两个
struct
A
和B
,并且都以一个数据成员char
开头,然后是一个数据成员int
(以及之后的任何其他字符),那么当您将它们放在union
中,您可以编写B
成员并通过其A
成员读取char
和int
,因此C ++也会这样做: 解决方案
Why is the compiler forbidden (by the standard) from reordering the struct?
The basic reason is: for compatibility with C.
Remember that C is, originally, a high-level assembly language. It is quite common in C to view memory (network packets, ...) by reinterpreting the bytes as a specific struct
.
This has led to multiple features relying on this property:
C guaranteed that the address of a
struct
and the address of its first data member are one and the same, so C++ does too (in the absence ofvirtual
inheritance/methods).C guaranteed that if you have two
struct
A
andB
and both start with a data memberchar
followed by a data memberint
(and whatever after), then when you put them in aunion
you can write theB
member and read thechar
andint
through itsA
member, so C++ does too: Standard Layout.
The latter is extremely broad, and completely prevents any re-ordering of data members for most struct
(or class
).
Note that the Standard does allow some re-ordering: since C did not have the concept of access control, C++ specifies that the relative order of two data members with a different access control specifier is unspecified.
As far as I know, no compiler attempts to take advantage of it; but they could in theory.
Outside of C++, languages such as Rust allow compilers to re-order fields and the main Rust compiler (rustc) does so by default. Only historical decisions and a strong desire for backward compatibility prevent C++ from doing so.
这篇关于编译器对结构进行重新排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!