在C+中,结构如何在内存中布局+;? 是标准配置的C++结构的方式,或者至少在编译器之间的通用性?

在C+中,结构如何在内存中布局+;? 是标准配置的C++结构的方式,或者至少在编译器之间的通用性?,c++,visual-c++,memory,gcc,struct,C++,Visual C++,Memory,Gcc,Struct,我有一个结构,其中一个成员需要在16字节边界上对齐,如果我能保证字段的顺序,这将更容易 另外,对于非虚拟类,第一个元素的地址也可能是结构的地址吗 我对GCC和msv最感兴趣。C++继承了C在许多平台上高效工作的需要/愿望,因此将某些事情留给了编译器。除了要求元素按指定的顺序显示外,这是其中之一 但许多编译器支持#pragma和选项,让您可以建立对打包的控制。请参阅编译器的文档 是C++结构的布局方式 由标准设置,或者至少 编译器之间的通用性 标准中没有保证。我不指望编译器具有相同的对齐方式 我有

我有一个结构,其中一个成员需要在16字节边界上对齐,如果我能保证字段的顺序,这将更容易

另外,对于非虚拟类,第一个元素的地址也可能是结构的地址吗


我对GCC和msv最感兴趣。

C++继承了C在许多平台上高效工作的需要/愿望,因此将某些事情留给了编译器。除了要求元素按指定的顺序显示外,这是其中之一

但许多编译器支持
#pragma
和选项,让您可以建立对打包的控制。请参阅编译器的文档

是C++结构的布局方式 由标准设置,或者至少 编译器之间的通用性

标准中没有保证。我不指望编译器具有相同的对齐方式

我有一个结构,其中一个 成员需要在16字节上对齐 边界,这会更容易 如果我能保证订货的话 田地

编译器不会更改字段的顺序

下面是一些关于如何为GCC和MSVC设置它们的链接:
对于GCC:
MSVC:以及


我会将它们作为结构保存,并使用外部“C”确保其正常工作。可能不需要,但这肯定会起作用。

结构在内存中按顺序排列。但是,它们在内存中的排列方式因操作系统而异

对于大于4字节的内容,Windows和Linux之间存在差异。Linux将它们对齐,就像它们是4个字节一样,因此,例如,双精度(8个字节)可以从p+4、p+8、p+12开始,等等,其中p是结构的开始。在Windows中,一个双(8字节)需要在一个8倍的地址开始,所以p+1,p+16,p+24,等等。

< p> c>代码>结构> /Cord>s(和C++ POD,用于兼容性)。
<> P>编译器之间唯一的区别是对齐,但幸运的是,MSVC和GCC都支持<代码> > PrimaMARPACT/<代码>。

< P> C和C++都保证了字段将按照定义的顺序排列在内存中。对于C++,它只保证了POD类型1(任何一个合法的C结构)[Ed:C89/90——例如,C99 VLA]也将作为POD的资格。 编译器可以自由地在成员之间和/或在结构的末尾插入填充。大多数编译器为您提供了某种控制方法(例如,
#pragma pack(N)
),但编译器之间确实存在差异

1嗯,有一个他们没有想到的极端情况,即POD类型不能保证——访问说明符违反了订购保证:

struct x { 
    int x;
    int y;
public:
    int z;
};
这是一种POD类型,但
public:
介于
y
z
之间意味着理论上可以重新订购。不过,我很确定这纯粹是理论上的——我不知道有哪种编译器会在这种情况下对成员进行重新排序(除非今天的内存故障比平时更严重,否则这在C++0x中是固定的)

编辑:本标准的相关部分(至少大部分)为§9/4:

POD结构是一个聚合类,没有非易失性 指针指向成员、非POD结构、非- POD联合(或此类类型的数组)或引用,并且没有 用户定义的复制分配运算符,无用户定义的复制分配运算符 析构函数

和§8.5.1/1:

聚合是一个数组或类(第9条),没有用户- 声明的施工人员(12.1),无私人或受保护的非 静态数据成员(第11条),无基类(第10条) 没有虚拟功能(10.3)

和§9.2/12:

…非静态数据成员的分配顺序 未指定由访问说明符分隔的(11.1)

尽管这在一定程度上受到§9.2/17的限制:

指向POD结构对象的指针,使用 一个重新解释的演员,指向其最初的成员

因此,(即使前面有一个
public:
,您定义的第一个成员在内存中也必须排在第一位。由
public:
说明符分隔的其他成员理论上可以重新排列

我还应该指出,关于这一点有一些争论的余地。特别是§9.2/14中也有一条规则:

如果两个POD结构(第9条)类型具有相同数量的非静态数据成员,则它们是布局兼容的,并且相应的非静态数据成员(按顺序)具有布局兼容的类型(3.9)

因此,如果您有以下情况:

struct A { 
    int x;
public:
    int y;
public:
    int z;
};
要求其布局与以下内容兼容:

struct B {
    int x;
    int y;
    int z;
};

我很确定这意味着两个结构的成员在内存中的布局必须相同。因为第二个结构显然不能重新排列其成员,所以第一个结构也不应该。不幸的是,该标准从未真正定义什么是“布局兼容”意味着,使参数充其量也很弱。

如果希望在MSVC下查看内存中所有类类型的内存布局,请将
/d1reportAllClassLayout
开关添加到编译器命令行


如果你想知道一个类的布局是什么样的,可以添加
/d1reportSingleClassLayoutNNNNN
,其中
NNNNN
是类的名称。

@Dan04:看我的答案——虽然委员会当然打算让POD有这个要求,但忽略了一个奇怪的角落,所以这个要求并不适用于所有的POD类型@jerry:如果你能为我们其他人的利益提供一些关于这个“奇怪的角落案例”的参考,那将是非常有用的。你有更大的问题。堆对齐通常不比8好。例如