标准布局结构的成员偏移量的 C++ 标准

Dan*_*tts 0 c++ struct c++11

C++11 标准是否保证所有编译器将为给定标准布局结构中的所有成员选择相同的内存偏移量,假设所有成员都有保证的大小(例如,int32_t而不是int)?

也就是说,对于标准布局结构中的给定成员,C++11 是否保证offsetof在所有编译器中给出相同的值?

如果是这样,是否有任何关于该值的规范,例如作为结构成员的大小、对齐和顺序的函数?

Jer*_*fin 6

不能保证 offsetof 在各个编译器中会产生相同的值。

关于类型的最小大小(例如,char>= 8 位、short> int= 16 位、long>= 32 位、 >= 64 位)以及大小1long long之间的关系( <= <= <= <= ) 有保证。sizeof(char)sizeof(short)sizeof(int)sizeof(long)sizeof(long long)

对于大多数类型,可以保证对齐要求不大于类型的大小。

对于任何struct/ class,第一个(非静态2)元素必须位于class/的开头struct,并且在不更改可见性的情况下,顺序保证按照定义的顺序。例如:

struct { // same if you use `class`
    int a;
    int b;
};
Run Code Online (Sandbox Code Playgroud)

由于它们都是公开的,a并且b必须按该顺序排列。但:

struct {
    int a;
    int b;
private:
    int c;
};
Run Code Online (Sandbox Code Playgroud)

第一个元素 ( a) 必须位于结构体的开头,但由于从public到 的更改private,编译器(理论上)允许排列c在 before 之前b

但随着时间的推移,这条规则已经发生了变化。在 C++98 中,即使是空的可见性说明符也允许重新排列成员。

struct A {
    int a;
    int b;
public:
    int c;
};
Run Code Online (Sandbox Code Playgroud)

即使它们都是公开的,也允许public重新排列。从那时起,它就被收紧了,所以它只是具有不同可见性的元素,并且在 C++ 23 中,基于可见性重新排列元素的整个想法已经消失了(在我看来,很久以前了——我认为没有人使用过它,所以这一直是你需要知道的规则,但没有人真正有任何好处)。bc


  1. 如果你想获得真正的技术性,要求实际上并不是尺寸,而是范围,因此理论上尺寸之间的关系并不能完全保证,但对于大多数实际目的来说,是这样的。
  2. 静态元素通常根本不被分配为类/结构对象的一部分。静态成员基本上被分配为全局变量,但有一些关于其名称可见性的额外规则。