MinGW和C++11中使用的紧凑结构体对齐问题

3
对于下面的结构体,在没有填充的情况下,结构体的实际大小为54。在64位(Windows 7)机器上使用MinGW(GCC)4.8.1 x86_64时,我得到了sizeof(BMPHeader)结果为56,这是可以理解的。根据BMP文件格式的要求,结构体不应有填充。我有三个选项(按优先级排序):
  1. C++11的 alignas(1)
  2. struct __attribute__ ((packed)) BMPHeader
  3. #pragma pack(1)
然而,只使用最后一个选项(优先级最低)似乎能够让我得到54。这是编译器的bug吗?还是我完全弄错了什么? SSCCE
#include <iostream>

struct alignas(1) BMPHeader
{
    // BMP header
    uint16_t magic;
    uint32_t fileSize;
    uint32_t reserved;
    uint32_t dataOffset;

    // DIB header
    uint32_t dibHeaderLength;
    uint32_t width;
    uint32_t height;
    uint16_t numColourPlanes;
    uint16_t bitsPerPixels;
    uint32_t biBitFields;
    uint32_t dataSize;
    uint32_t physicalWidth;
    uint32_t physicalHeight;
    uint32_t numPaletteColours;
    uint32_t numImportantColours;
};

int main()
{
    std::cout << sizeof(BMPHeader) << std::endl;
}

3
alignas(1) 无效。这意味着你不能请求比自然对齐更松散的对齐方式。 - R. Martinho Fernandes
1个回答

5
  1. alignas在这种情况下不能使用,因为我们要求的对齐方式比结构体的自然对齐方式更宽松。这在标准中已经说明了,在dcl.align(强调相关部分)中指定:

当为实体指定多个对齐说明符时,对齐要求应设置为最严格的指定对齐。

声明中所有对齐说明符的组合效果不得指定比省略所有对齐说明符(包括其他声明中的说明符)所需的对齐方式更宽松的对齐方式

BMPHeader的对齐方式由alignof(BMPHeader)返回的值为4,因此任何比它更宽松的对齐方式都将被忽略。

  1. __attribute__ ((packed))在使用GCC时肯定是正确的方法,正如其手册中所述,可以使结构紧密地打包。然而,由于MinGW中的一个错误,这种方法不起作用,在使用GCC时可以正常工作

  2. 因此,目前在MinGW中唯一的方法是使用#pragma pack(1)。请参见#pragma pack effect了解此方法的更多详细信息。

另请参阅


此答案中链接的错误可能已在gcc 8中得到修复。请参见此评论 - AJM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接