MinGW и выравнивание упакованных структур с использованием C ++ 11

Для приведенной ниже структуры фактический (без заполнения) размер структуры равен 54. На 64-битной (Windows 7) машине с MinGW (GCC) 4.8.1 x86_64 я получаю sizeof(BMPHeader) как 56, что понятно. Согласно требованиям формата файла BMP, структура не должна иметь отступов. Есть три варианта (в порядке приоритета):

  1. C++11's alignas(1)
  2. struct __attribute__ ((packed)) BMPHeader
  3. #pragma pack(1)

Однако последний вариант (с наименьшим приоритетом), кажется, работает, давая мне 54. Это ошибка в компиляторе, или я что-то здесь ошибся? 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;
}

person legends2k    schedule 22.11.2013    source источник
comment
alignas(1) не работает. При этом вы не можете требовать выравнивания менее строгого, чем естественное выравнивание.   -  person R. Martinho Fernandes    schedule 22.11.2013


Ответы (1)


  1. alignas нельзя использовать в этой ситуации, как отмечает Мартиньо, поскольку мы требуем менее строгого выравнивания, чем естественное выравнивание структуры. Это указано в стандарте в разделе dcl.align (выделена соответствующая часть):

Когда для объекта указано несколько спецификаторов выравнивания, требование выравнивания должно быть установлено на самое строгое заданное выравнивание.

Комбинированный эффект всех спецификаторов выравнивания в объявлении не должен указывать менее строгое выравнивание, чем выравнивание, которое потребовалось бы для объявляемого объекта, если бы все спецификаторы выравнивания были опущены (включая те, что в другие декларации).

Выравнивание BMPHeader, возвращенное alignof(BMPHeader), равно 4, и, следовательно, любое менее строгое (менее широкое) выравнивание не будет соблюдаться.

  1. __attribute__ ((packed)), безусловно, правильный путь при использовании GCC в качестве указано в его руководстве, чтобы структура была плотно упакована. Однако это не работает из-за ошибки в MinGW и отлично работает при использовании GCC.

  2. Так что в настоящее время единственный способ в MinGW - это использовать #pragma pack(1). Подробнее об этом методе см. #pragma pack effect.

person legends2k    schedule 25.07.2015