关于c ++中的结构填充

时间:2013-02-04 10:07:15

标签: c++ visual-studio-2008

我在项目中使用数据结构,在特定结构的上下文中,我对结构填充有疑问。首先看下面给出的结构。我使用Visual Studio 2008编译器。

typedef struct tagDATA_PACK
{
   DWORD dDataLength;
   BYTE bFlags;
   BYTE bAttrib;
   BYTE bOffset;
}DATA_PACK;
问题1:上述结构的大小是多少?    它显示8个字节。它是正确的。但是,

考虑下面给出的修改结构?

typedef struct tagDATA_PACK
{
   DWORD dDataLength;
   BYTE bFlags;
}DATA_PACK;

这里的大小与上述8字节结构相同。 我怀疑的是,编译器在哪里添加额外的3字节? 是在BYTE bFlags之后还是之前呢?

非常感谢您的所有答案。

4 个答案:

答案 0 :(得分:4)

标准未指定结构和类的对齐和填充。这完全取决于编译器。但是,所有理智的编译器都遵循底层平台ABI。在您的情况下,该平台是Windows,并且遵守Windows平台ABI。

在这种情况下,两个结构的填充都在最后一个成员之后。第一个结构有一个额外的填充字节,第二个结构有三个额外的填充字节。

结构中最大的类型大小为4.这意味着整体大小将是4的倍数。对于两个结构,容纳结构的4的最小倍数是8。

每种数据类型都有一个对齐属性。 4字节数据类型具有4的对齐.2字节数据类型具有2的对齐。当放置在距结构的开始的4字节偏移处时,对齐为4的类型被对齐。对齐为2的类型在放置在距结构开头2字节偏移处时对齐。等等。

成员被置于最小的偏移量,该偏移量既包括成员声明的顺序,也包括成员的对齐属性。

对于结构内部填充的示例,请考虑此结构

struct MyStruct
{
   char c;
   int i;
};

c的对齐方式为1,i的对齐方式为4.因此,c位于1字节边界,i必须放置在4字节边界上。这意味着c将偏移0,然后将有3个填充字节,然后i将以4的偏移量布局。

答案 1 :(得分:1)

编译器想要的地方。如果重要的话,你还是做了一些非便携的东西,为什么这很重要?

答案 2 :(得分:1)

虽然所有答案都说这取决于编译器是正确的,因为 直到编译器,语言规范对布局有一些限制。这些限制适用于C中的所有结构,C ++ 03中的“普通旧数据”(基本上只表示使用C中的特性)和C ++ 11中的“标准布局”结构(允许使用构造函数和析构函数)。限制是:

  • (重新解释)将指向结构的指针转换为第一个成员的类型,生成指向第一个成员的有效指针(C ++11§9.2/ 20)。这意味着在第一个成员之前不能填充。
  • 如果联合中的两个结构具有相同的初始部分(相同类型的成员以相同的顺序)并且通过其中一个初始化联合,则可以通过另一个访问这些初始成员(C ++11§) 9.2 / 19)。这意味着成员偏移量可能只取决于之前声明的成员。

对标准布局的限制很重要。对于具有基类或虚拟成员的类都不适用。

现在,当结合不浪费内存的愿望时,这实际上只留下了一个实用的算法,因此所有编译器都使用它。这并不意味着所有编译器将为相同的输入生成相同的布局,因为各种基元类型的大小和对齐要求在平台之间是不同的。算法是:

  • 在偏移0处布置第一个成员。
  • 在第一个可用的偏移处布置每个跟随的成员,该偏移可以被所需的对齐整除。
  • 将结构的大小舍入到任何成员的下一个最大对齐倍数。
  • 结构的对齐要求是任何成员的最大对齐方式。

(我几乎肯定MSVC ++的MSDN在某处描述了这个,但无法快速找到它)

答案 3 :(得分:0)

看看这个:

typedef struct myTagDATA_PACK3
{
    char c;
    double d;
    int i;
}DATA_PACK3;

它显示24个字节。那是: double:8个字节。 int:4个字节+(4个字节填充)= 8个字节。 char:1个字节+(7个字节填充)= 8个字节。


总计:24个字节。