我在项目中使用数据结构,在特定结构的上下文中,我对结构填充有疑问。首先看下面给出的结构。我使用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之后还是之前呢?
非常感谢您的所有答案。
答案 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中的“标准布局”结构(允许使用构造函数和析构函数)。限制是:
对标准布局的限制很重要。对于具有基类或虚拟成员的类都不适用。
现在,当结合不浪费内存的愿望时,这实际上只留下了一个实用的算法,因此所有编译器都使用它。这并不意味着所有编译器将为相同的输入生成相同的布局,因为各种基元类型的大小和对齐要求在平台之间是不同的。算法是:
(我几乎肯定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个字节。