1

我在我的项目中使用数据结构,并且在特定结构的上下文中,我对结构填充有疑问。首先看下面给出的结构。我使用 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;

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

非常感谢您的所有回答。

4

4 回答 4

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 处布局。

于 2013-02-04T10:10:06.270 回答
1

编译器想要的任何地方。如果它很重要,那么无论如何你都在做一些不可移植的事情,那为什么重要呢?

于 2013-02-04T10:10:58.803 回答
1

虽然所有关于编译器的答案都是正确的,因为这取决于编译,语言规范对布局设置了一些限制。这些限制适用于 C 中的所有结构、C++03 中的“普通旧数据”(基本上意味着仅使用 C 中的功能)和 C++11 中的“标准布局”结构(允许具有构造函数和析构函数)。限制是:

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

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

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

  • 在偏移量 0 处布置第一个成员。
  • Lay out each following member at first available offset divisible by it's required alignment.
  • Round the size of the structure up to the next multiple of largest alignment of any member.
  • Alignment requirement of the structure is the largest alignment of any member.

(I am almost certain MSDN for MSVC++ describes this somewhere, but couldn't quickly find it)

于 2013-02-04T10:48:49.290 回答
0

看看这个:

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

它显示 24 个字节。即:双:8字节。int:4 字节 +(4 字节填充)= 8 字节。字符:1 字节 +(7 字节填充)= 8 字节。


总计:24 字节。

于 2013-02-04T10:39:51.683 回答